该备忘单是针对 Java 初学者的速成课程,有助于复习 Java 语言的基本语法。
public class Hello {// 主要方法public static void main(String[] args){// 输出: Hello, world!System.out.println("Hello, world!");}}
编译和运行
$ javac Hello.java$ java HelloHello, world!
int num = 5;float floatNum = 5.99f;char letter = 'D';boolean bool = true;String site = "jaywcjlove.github.io";
数据类型 | 大小 | 默认 | 范围 |
---|---|---|---|
byte | 1 byte | 0 | -128 ^to^ 127 |
short | 2 byte | 0 | -2^15^ ^to^ 2^15^-1 |
int | 4 byte | 0 | -2^31^ ^to^ 2^31^-1 |
long | 8 byte | 0 | -2^63^ ^to^ 2^63^-1 |
float | 4 byte | 0.0f | N/A |
double | 8 byte | 0.0d | N/A |
char | 2 byte | \u0000 | 0 ^to^ 65535 |
boolean | N/A | false | true / false |
String first = "John";String last = "Doe";String name = first + " " + last;System.out.println(name);
查看: Strings
String word = "QuickRef";for (char c: word.toCharArray()) {System.out.print(c + "-");}// 输出: Q-u-i-c-k-R-e-f-
查看: Loops
char[] chars = new char[10];chars[0] = 'a'chars[1] = 'b'String[] letters = {"A", "B", "C"};int[] mylist = {100, 200};boolean[] answers = {true, false};
查看: Arrays
int a = 1;int b = 2;System.out.println(a + " " + b); // 1 2int temp = a;a = b;b = temp;System.out.println(a + " " + b); // 2 1
// Widening// byte<short<int<long<float<doubleint i = 10;long l = i; // 10// Narrowingdouble d = 10.02;long l = (long)d; // 10String.valueOf(10); // "10"Integer.parseInt("10"); // 10Double.parseDouble("10"); // 10.0
int j = 10;if (j == 10) {System.out.println("I get printed");} else if (j > 10) {System.out.println("I don't");} else {System.out.println("I also don't");}
查看: [Conditionals](#条件语句 Conditionals)
Scanner in = new Scanner(System.in);String str = in.nextLine();System.out.println(str);int num = in.nextInt();System.out.println(num);
String str1 = "value";String str2 = new String("value");String str3 = String.valueOf(123);
String s = 3 + "str" + 3; // 3str3String s = 3 + 3 + "str"; // 6strString s = "3" + 3 + "str"; // 33strString s = "3" + "3" + "23"; // 3323String s = "" + 3 + 3 + "23"; // 3323String s = 3 + 3 + 23; // 29
StringBuilder sb = new StringBuilder(10);
┌───┬───┬───┬───┬───┬───┬───┬───┬───┐| | | | | | | | | |└───┴───┴───┴───┴───┴───┴───┴───┴───┘0 1 2 3 4 5 6 7 8 9
sb.append("Reference");
┌───┬───┬───┬───┬───┬───┬───┬───┬───┐| R | e | f | e | r | e | n | c | e |└───┴───┴───┴───┴───┴───┴───┴───┴───┘0 1 2 3 4 5 6 7 8 9
sb.delete(3, 9);
┌───┬───┬───┬───┬───┬───┬───┬───┬───┐| R | e | f | | | | | | |└───┴───┴───┴───┴───┴───┴───┴───┴───┘0 1 2 3 4 5 6 7 8 9
sb.insert(0, "My ");
┌───┬───┬───┬───┬───┬───┬───┬───┬───┐| M | y | | R | e | f | | | |└───┴───┴───┴───┴───┴───┴───┴───┴───┘0 1 2 3 4 5 6 7 8 9
sb.append("!");
┌───┬───┬───┬───┬───┬───┬───┬───┬───┐| M | y | | R | e | f | ! | | |└───┴───┴───┴───┴───┴───┴───┴───┴───┘0 1 2 3 4 5 6 7 8 9
String s1 = new String("QuickRef");String s2 = new String("QuickRef");s1 == s2 // falses1.equals(s2) // true"AB".equalsIgnoreCase("ab") // true
String str = "Abcd";str.toUpperCase(); // ABCDstr.toLowerCase(); // abcdstr.concat("#"); // Abcd#str.replace("b", "-"); // A-cd" abc ".trim(); // abc"ab".toCharArray(); // {'a', 'b'}
String str = "abcd";str.charAt(2); // cstr.indexOf("a") // 0str.indexOf("z") // -1str.length(); // 4str.toString(); // abcdstr.substring(2); // cdstr.substring(2,3); // cstr.contains("c"); // truestr.endsWith("d"); // truestr.startsWith("a"); // truestr.isEmpty(); // false
String str = "hello";str.concat("world");// 输出: helloSystem.out.println(str);
String str = "hello";String concat = str.concat("world");// 输出: helloworldSystem.out.println(concat);
一旦创建就不能修改,任何修改都会创建一个新的String
int[] a1;int[] a2 = {1, 2, 3};int[] a3 = new int[]{1, 2, 3};int[] a4 = new int[3];a4[0] = 1;a4[2] = 2;a4[3] = 3;
int[] a = {1, 2, 3};System.out.println(a[0]); // 1a[0] = 9;System.out.println(a[0]); // 9System.out.println(a.length); // 3
int[] arr = {1, 2, 3};for (int i=0; i < arr.length; i++) {arr[i] = arr[i] * 2;System.out.print(arr[i] + " ");}// 输出: 2 4 6
String[] arr = {"a", "b", "c"};for (int a: arr) {System.out.print(a + " ");}// 输出: a b c
int[][] matrix = { {1, 2, 3}, {4, 5} };int x = matrix[1][0]; // 4// [[1, 2, 3], [4, 5]]Arrays.deepToString(matrix)for (int i = 0; i < a.length; ++i) {for(int j = 0; j < a[i].length; ++j) {System.out.println(a[i][j]);}}// 输出: 1 2 3 4 5 6 7
char[] chars = {'b', 'a', 'c'};Arrays.sort(chars);// [a, b, c]Arrays.toString(chars);
+
(加法运算符(也用于字符串连接))-
(减法运算符)*
(乘法运算符)/
(分区运算符)%
(余数运算符)=
(简单赋值运算符)++
(增量运算符;将值增加 1)--
(递减运算符;将值减 1)!
(逻辑补码运算符;反转布尔值)==
(等于)!=
(不等于)>
(比...更棒)>=
(大于或等于)<
(少于)<=
(小于或等于)&&
条件与||
条件或instanceof
(将对象与指定类型进行比较)~
(一元按位补码)<<
(签名左移)>>
(有符号右移)>>>
(无符号右移)&
(按位与)^
(按位异或)|
(按位包含 OR)int k = 15;if (k > 20) {System.out.println(1);} else if (k > 10) {System.out.println(2);} else {System.out.println(3);}
int month = 3;String str;switch (month) {case 1:str = "January";break;case 2:str = "February";break;case 3:str = "March";break;default:str = "Some other month";break;}// 输出: Result MarchSystem.out.println("Result " + str);
int a = 10;int b = 20;int max = (a > b) ? a : b;// 输出: 20System.out.println(max);
// 与运算if (condition1 && condition2) {// 如果 condition1 和 condition2 都成立// 则执行此处的代码}// 或运算if (condition1 || condition2) {// 如果condition1或condition2任意一个成立// 则执行此处的代码}// 非运算if (!condition) {// 如果条件不成立,则执行此处的代码}
// 等于if (a == b) {// 如果a等于b,则执行此处的代码}// 不等于if (a != b) {// 如果a不等于b,则执行此处的代码}// 大于、大于等于、小于、小于等于if (a > b) {}if (a >= b) {}if (a < b) {}if (a <= b) {}
for (int i = 0; i < 10; i++) {System.out.print(i);}// 输出: 0123456789
for (int i = 0,j = 0; i < 3; i++,j--) {System.out.print(j + "|" + i + " ");}// 输出: 0|0 -1|1 -2|2
int[] numbers = {1,2,3,4,5};for (int number: numbers) {System.out.print(number);}// 输出: 12345
用于循环数组或列表
int count = 0;while (count < 5) {System.out.print(count);count++;}// 输出: 01234
int count = 0;do {System.out.print(count);count++;} while (count < 5);// 输出: 01234
for (int i = 0; i < 5; i++) {if (i == 3) {continue;}System.out.print(i);}// 输出: 01245
for (int i = 0; i < 5; i++) {System.out.print(i);if (i == 3) {break;}}// 输出: 0123
// 实现Runnable接口public class RunnableThread implements Runnable {@Overridepublic void run() {// todo something}}
实现Callable接口,T 替换成实际类型
public class CallableTask implements Callable<T> {@Overridepublic T call() throws Exception {// todo somethingreturn null;}}
继承Thrad类
public class ExtendsThread extends Thread {@Overridepublic void run() {// todo something}}
运行线程
public static void main(String[] args) throws ExecutionException, InterruptedException {new Thread(new RunnableThread()).start();new ExtendsThread2().start();FutureTask<Integer> integerFutureTask = new FutureTask<>(new CallableTask());integerFutureTask.run();}
ThreadPoolExecutor threadPoolExecutor= new ThreadPoolExecutor(2, 5,5, TimeUnit.SECONDS,new ArrayBlockingQueue<>(10),new DefaultThreadFactory("pollName"),new ThreadPoolExecutor.CallerRunsPolicy());// 内置的线程池, 不推荐生产使用Executors.newCachedThreadPool();Executors.newFixedThreadPool(10);Executors.newScheduledThreadPool(10);Executors.newSingleThreadExecutor();
// 代码块synchronized(obj) {...}// (静态)方法public synchronized(static) void methodName() {...}
// CountDownLatchCountDownLatch countDownLatch = new CountDownLatch(2);new Thread(() -> {try {...}finally {countDownLatch.countDown();}}).start();countDownLatch.await();
CompletableFuture
CompletableFuture<Void> task1 = CompletableFuture.runAsync(() -> {});CompletableFuture<Void> task2 = CompletableFuture.runAsync(() -> {});CompletableFuture<Void> task3 = CompletableFuture.runAsync(() -> {});CompletableFuture.allOf(task1, task2, task3).get();
Semaphore
Semaphore semaphore = new Semaphore(5);try {semaphore.acquire();} finally {semaphore.release();}
ThreadLocal<Integer> threadLocal= new ThreadLocal<>();
使用完之后一定要记得 remove
, 否则会内存泄露
threadLocal.set(1);threadLocal.get();threadLocal.remove();
// 需要synchronized修饰的代码块才能使用wait();notify();notifyAll();// 使用lock的条件唤醒ReentrantLock lock = new ReentrantLock();Condition condition= lock.newCondition();lock.lock();try{// 当前线程唤醒或等待condition.await();condition.signal();condition.signalAll();} finally {lock.unlock}// LockSupport,可以先unpark,后续park不会阻塞线程LockSupport.park(obj);LockSupport.unpark(thread);
集合 | Interface | 有序 | 已排序 | 线程安全 | 复制 | Nullable |
---|---|---|---|---|---|---|
ArrayList | List | Y | N | N | Y | Y |
Vector | List | Y | N | Y | Y | Y |
LinkedList | List, Deque | Y | N | N | Y | Y |
CopyOnWriteArrayList | List | Y | N | Y | Y | Y |
HashSet | Set | N | N | N | N | One null |
LinkedHashSet | Set | Y | N | N | N | One null |
TreeSet | Set | Y | Y | N | N | N |
CopyOnWriteArraySet | Set | Y | N | Y | N | One null |
ConcurrentSkipListSet | Set | Y | Y | Y | N | N |
HashMap | Map | N | N | N | N (key) | One null (key) |
HashTable | Map | N | N | Y | N (key) | N (key) |
LinkedHashMap | Map | Y | N | N | N (key) | One null (key) |
TreeMap | Map | Y | Y | N | N (key) | N (key) |
ConcurrentHashMap | Map | N | N | Y | N (key) | N |
ConcurrentSkipListMap | Map | Y | Y | Y | N (key) | N |
ArrayDeque | Deque | Y | N | N | Y | N |
PriorityQueue | Queue | Y | N | N | Y | N |
ConcurrentLinkedQueue | Queue | Y | N | Y | Y | N |
ConcurrentLinkedDeque | Deque | Y | N | Y | Y | N |
ArrayBlockingQueue | Queue | Y | N | Y | Y | N |
LinkedBlockingDeque | Deque | Y | N | Y | Y | N |
PriorityBlockingQueue | Queue | Y | N | Y | Y | N |
List<Integer> nums = new ArrayList<>();// 添加nums.add(2);nums.add(5);nums.add(8);// 检索System.out.println(nums.get(0));// 为循环迭代编制索引for (int i = 0; i < nums.size(); i++) {System.out.println(nums.get(i));}nums.remove(nums.size() - 1);nums.remove(0); // 非常慢for (Integer value : nums) {System.out.println(value);}// lambda 打印元素nums.forEach(e -> System.out.println(e.toString()));
Map<Integer, String> m = new HashMap<>();m.put(5, "Five");m.put(8, "Eight");m.put(6, "Six");m.put(4, "Four");m.put(2, "Two");// 检索System.out.println(m.get(6));// Lambda forEachm.forEach((key, value) -> {String msg = key + ": " + value;System.out.println(msg);});
ConcurrentHashMap<Integer, String> m= new ConcurrentHashMap<>();m.put(100, "Hello");m.put(101, "Geeks");m.put(102, "Geeks");// 移除m.remove(101, "Geeks");// 如果不存在,就添加,存在就不变更m.putIfAbsent(103, "Hello");// 替换m.replace(101, "Hello", "For");System.out.println(m);
Set<String> set = new HashSet<>();if (set.isEmpty()) {System.out.println("Empty!");}set.add("dog");set.add("cat");set.add("mouse");set.add("snake");set.add("bear");if (set.contains("cat")) {System.out.println("Contains cat");}set.remove("cat");for (String element : set) {System.out.println(element);}set.forEach(e -> System.out.println(e.toString()));
Deque<String> a = new ArrayDeque<>();// 使用 add()a.add("Dog");// 使用 addFirst()a.addFirst("Cat");// 使用 addLast()a.addLast("Horse");// [Cat, Dog, Horse]System.out.println(a);// 访问元素System.out.println(a.peek());// 移除元素System.out.println(a.pop());
字节流
InputStream
字节输入流的抽象基类FileInputStream
从文件中读取字节的输入流ByteArrayInputStream
从字节数组中读取字节的输入流OutputStream
字节输出流的抽象基类FileOutputStream
向文件中写入字节的输出流ByteArrayOutputStream
将字节写入到字节数组的输出流字符流
Reader
字符输入流的抽象基类FileReader
从文件中读取字符的输入流BufferedReader
带缓冲区的字符输入流InputStreamReader
字节流到字符流的桥接器Writer
字符输出流的抽象基类FileWriter
向文件中写入字符的输出流BufferedWriter
带缓冲区的字符输出流OutputStreamWriter
字符流到字节流的桥接器对象流
ObjectInputStream
从输入流中读取Java对象的流ObjectOutputStream
将Java对象写入输出流的流缓冲流
BufferedInputStream
带缓冲区的字节输入流BufferedOutputStream
带缓冲区的字节输出流BufferedReader
带缓冲区的字符输入流BufferedWriter
带缓冲区的字符输出流数据流
DataInputStream
从输入流中读取基本数据类型的数据DataOutputStream
将基本数据类型数据写入输出流文件类
File
文件和目录路径名的抽象表示FileReader
从文件中读取字符的输入流FileWriter
向文件中写入字符的输出流输入输出异常处理
IOException
Java I/O操作中的通用异常FileNotFoundException
当试图打开指定文件失败时抛出EOFException
在尝试读取流的末尾时抛出其他流
PrintStream
打印格式化表示的对象的输出流PrintWriter
格式化的文本输出流RandomAccessFile
随机访问文件的类,支持读取和写入操作// 文件输入流InputStream inputStream= new FileInputStream("input.txt");// 文件输出流OutputStream outputStream= new FileOutputStream("output.txt");// 缓冲字节输入流InputStream bufferedInputStream= new BufferedInputStream(inputStream);// 缓冲字节输出流OutputStream bufferedOutputStream= new BufferedOutputStream(outputStream);
// 文件字符输入流Reader fileReader= new FileReader("input.txt");// 文件字符输出流Writer fileWriter= new FileWriter("output.txt");// 缓冲字符输入流Reader bufferedFileReader= new BufferedReader(new FileReader("input.txt"));// 缓冲字符输出流Writer bufferedFileWriter= new BufferedWriter(new FileWriter("output.txt"));
// 数据输入流DataInputStream dataInputStream= new DataInputStream(inputStream);// 数据输出流DataOutputStream dataOutputStream= new DataOutputStream(outputStream);
// 对象输入流ObjectInputStream objectInputStream= new ObjectInputStream(inputStream);// 对象输出流ObjectOutputStream objectOutputStream= new ObjectOutputStream(outputStream);
序列化对象到文件
try (ObjectOutputStream objectOutputStream= new ObjectOutputStream(new FileOutputStream("object.dat"))) {objectOutputStream.writeObject(object);}
从文件反序列化对象
try (ObjectInputStream objectInputStream= new ObjectInputStream(new FileInputStream("object.dat"))) {Object object = objectInputStream.readObject();}
标准输入流
InputStream standardInputStream= System.in;
标准输出流
PrintStream standardOutputStream= System.out;
// 读取字节数据int byteData = inputStream.read();// 写入字节数据outputStream.write(byteData);// 读取字符数据int charData = reader.read();// 写入字符数据writer.write(charData);
// 关闭输入流inputStream.close();// 关闭输出流outputStream.close();
从集合创建流
List<String> list = Arrays.asList("a", "b", "c");Stream<String> streamFromList = list.stream();
从数组创建流
String[] array = {"d", "e", "f"};Stream<String> streamFromArray = Arrays.stream(array);
创建空流
Stream<String> emptyStream = Stream.empty();
创建无限流
Stream<Integer> infiniteStream = Stream.iterate(0, n -> n + 2);
// 过滤Stream<String> filteredStream = list.stream().filter(s -> s.startsWith("a"));// 映射Stream<Integer> mappedStream = list.stream().map(String::length);// 排序Stream<String> sortedStream = list.stream().sorted();// 去重Stream<String> distinctStream = list.stream().distinct();// 截断Stream<String> limitedStream = list.stream().limit(2);// 跳过Stream<String> skippedStream = list.stream().skip(1);
// 聚合操作Optional<String> anyElement = list.stream().findAny();Optional<String> firstElement = list.stream().findFirst();long count = list.stream().count();Optional<String> maxElement = list.stream().max(Comparator.naturalOrder());Optional<String> minElement = list.stream().min(Comparator.naturalOrder());// 检查匹配boolean anyMatch = list.stream().anyMatch(s -> s.contains("a"));boolean allMatch = list.stream().allMatch(s -> s.length() == 1);boolean noneMatch = list.stream().noneMatch(s -> s.contains("z"));// 归约Optional<String> reducedString = list.stream().reduce((s1, s2) -> s1 + s2);String reducedStringWithIdentity = list.stream().reduce("Start:", (s1, s2) -> s1 + s2);// 收集List<String> collectedList = list.stream().collect(Collectors.toList());Set<String> collectedSet = list.stream().collect(Collectors.toSet());Map<Integer, String> collectedMap = list.stream().collect(Collectors.toMap(String::length, Function.identity()));
List<String> list = Arrays.asList("a", "b", "c", "d", "e");List<String> upperCaseList = list.parallelStream().map(String::toUpperCase).collect(Collectors.toList());
这些是使用 Java 反射时常见的操作。使用反射需要注意性能和安全性问题,尽量避免在性能要求高的地方过度使用。
// 通过类名获取Class对象Class<?> clazz1 = MyClass.class;// 通过对象获取Class对象MyClass obj = new MyClass();Class<?> clazz2 = obj.getClass();// 通过完整类名字符串获取Class对象Class<?> clazz3 = Class.forName("com.example.MyClass");
获取类的名称
String className = clazz.getName();
获取类的修饰符
int modifiers = clazz.getModifiers();
获取类的包信息
Package pkg = clazz.getPackage();
获取类的父类
Class<?> superClass = clazz.getSuperclass();
获取类实现的接口
Class<?>[] interfaces = clazz.getInterfaces();
// 使用默认构造函数创建对象MyClass instance = (MyClass) clazz.newInstance();// 使用带参数的构造函数创建对象Constructor<?> constructor = clazz.getConstructor(String.class, int.class);MyClass instanceWithArgs = (MyClass) constructor.newInstance("example", 123);
// 获取字段值Field field = clazz.getDeclaredField("fieldName");field.setAccessible(true); // 如果字段是私有的,需要设置可访问Object value = field.get(instance);// 设置字段值field.set(instance, newValue);
// 获取泛型信息Type genericType = field.getGenericType();
// 获取方法Method method = clazz.getDeclaredMethod("methodName", parameterTypes);method.setAccessible(true); // 如果方法是私有的,需要设置可访问// 调用方法Object result = method.invoke(instance, args);
// 判断是否是数组、枚举、注解等boolean isArray = clazz.isArray();boolean isEnum = clazz.isEnum();boolean isAnnotation = clazz.isAnnotation();// 获取构造函数、字段、方法等Constructor<?>[] constructors = clazz.getConstructors();Field[] fields = clazz.getDeclaredFields();Method[] methods = clazz.getDeclaredMethods();
// 获取注解信息Annotation annotation = field.getAnnotation(MyAnnotation.class);
Java 的 Consumer
接口里的 accept
方法接受参数但不返回值。要让它打印传入的参数,可以这样做:
Consumer<String> test = new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}};test.accept("test");
更简单的,我们可以直接传入Lambda表达式
Consumer<String> test = System.out::println;
方法引用通过方法的名字指向一个方法,使语言构造更简洁,减少冗余代码。
Comparator<Integer> comparator = Math::max;int result = comparator.compare(1, 2);// 返回 2
String str = "HELLO";String lowerCase = str::toLowerCase;// 返回 "hello"
Supplier<String> supplier = String::new;String str = supplier.get();// 返回一个空字符串
Function<Integer, String[]> function = String[]::new;String[] array = function.apply(5);// 返回 5 个空字符串的数组
String someStr = "HELLO";String lowerCase = someStr::toLowerCase;// 返回 "hello"
SomeClass someObject = new SomeClass();int result = someObject::staticMethod;// 调用静态方法
修饰符 | Class | Package | Subclass | World |
---|---|---|---|---|
public | Y | Y | Y | Y |
protected | Y | Y | Y | N |
no modifier | Y | Y | N | N |
private | Y | N | N | N |
String text = "I am learning Java";// 删除所有空格text.replaceAll("\\s+", "");// 拆分字符串text.split("\\|");text.split(Pattern.quote("|"));
查看: Regex in java
// 我是单行注释!/*而我是一个多行注释!*//*** 这个* 是* 文档* 注释*/
方法 | 说明 |
---|---|
Math.max(a,b) | a 和 b 的最大值 |
Math.min(a,b) | a 和 b 的最小值 |
Math.abs(a) | 绝对值 |
Math.sqrt(a) | a 的平方根 |
Math.pow(a,b) | b 的幂 |
Math.round(a) | 最接近的整数 |
Math.sin(ang) | 正弦 |
Math.cos(ang) | ang 的余弦 |
Math.tan(ang) | ang 的切线 |
Math.asin(ang) | ang 的反正弦 |
Math.log(a) | a 的自然对数 |
Math.toDegrees(rad) | 以度为单位的角度弧度 |
Math.toRadians(deg) | 以弧度为单位的角度度 |
try {// something} catch (Exception e) {e.printStackTrace();} finally {System.out.println("always printed");}
ArrayDeque
: 可调整大小的数组双端队列,实现了Deque接口Arrays
: 提供静态工厂,允许将数组视为列表Collections
: 包含操作集合或返回集合的静态方法Date
: 表示特定时间瞬间,精度为毫秒Dictionary
: 抽象父类,可用于键值对映射,例如HashtableEnumMap
: 专门用于枚举键的Map实现EnumSet
: 专门用于枚举键的Set实现Formatter
: 提供对布局、对齐、数字、字符串和日期/时间数据的格式化支持,以及特定于语言环境的输出SecureRandom
: 生成安全的伪随机数流的实例UUID
: 表示不可变的通用唯一标识符Vector
: 实现了可增长的对象数组LocalDate
: 表示无时区的日期,仅包含年月日,不可变且线程安全,适用于Java 8及更高版本LocalTime
: 表示无时区的时间,仅包含时分秒,不可变且线程安全,适用于Java 8及更高版本LocalDateTime
: 表示无时区的日期时间,包含年月日时分秒,不可变且线程安全,适用于Java 8及更高版本// 计算出现频率List<Integer> list = new ArrayList<>();list.add(1);list.add(2);list.add(2);list.add(3);list.add(3);list.add(3);int frequency = Collections.frequency(list, 2); // frequency = 2