OCA/OCP Java Note (7): Core Java APIs (2)
Contents
5. Understanding an ArrayList
与数组类似,ArrayList是一个有序序列,且允许重复与元素。数组中元素的个数在声明时就已经确定,不可再更改,ArrayList可以在运行时改变大小。
import java.util.* // import whole package including ArrayList import java.util.ArrayList; // import just ArrayList
5.1. Creating an ArrayList
Java 5之前可以使用以下的方法创建ArrayList,现在也可以使用,例如:
ArrayList list1 = new ArrayList(); ArrayList list2 = new ArrayList(10); ArrayList list3 = new ArrayList(list2);
Java 5引入了泛型(generics),可以在声明时指明ArrayList中所保存的类。从Java 7开始,可以省略等号右边的类型,但需要保留<>,例如:
ArrayList<String> list4 = new ArrayList(); ArrayList list5 = new ArrayList<>();
ArrayList实现了List接口,不能直接实例化List:
List<String> list6 = new ArrayList<>(); ArrayList list7 = new List<>(); // DOES NOT COMPILE
5.2. Using an ArrayList
5.2.1. add()
boolean add(E element) // always returns true void add(int index, E element)
eg.
ArrayList list = new ArrayList(); list.add("hawk"); // [hawk] list.add(Boolean.TRUE); // [hawk, true] System.out.println(list); // [hawk, true]
这里没有指明ArrayList中元素的类型,所以ArrayList中的元素为Object。
eg.
ArrayList<String> safer = new ArrayList<>(); safer.add("sparrow"); safer.add(Boolean.TRUE); // DOES NOT COMPILE
这里指明了ArrayList中元素的类型为String,不能放入Boolean。
eg.
4: List<String> birds = new ArrayList<>(); 5: birds.add("hawk"); // [hawk] 6: birds.add(1, "robin"); // [hawk, robin] 7: birds.add(0, "blue jay"); // [blue jay, hawk, robin] 8: birds.add(1, "cardinal"); // [blue jay, cardinal, hawk, robin] 9: System.out.println(birds); // [blue jay, cardinal, hawk, robin]
5.2.2. remove()
boolean remove(Object object) // 成功删除返回true E remove(int index) // 返回被删除的元素
eg.
3: List<String> birds = new ArrayList<>(); 4: birds.add("hawk"); // [hawk] 5: birds.add("hawk"); // [hawk, hawk] 6: System.out.println(birds.remove("cardinal")); // prints false 7: System.out.println(birds.remove("hawk")); // prints true 8: System.out.println(birds.remove(0)); // prints hawk 9: System.out.println(birds); // [] 10:birds.remove(100) // throws IndexOutOfBoundsException
5.2.3. set()
E set(int index, E newElement) // 返回被替换的元素
eg.
15: List<String> birds = new ArrayList<>(); 16: birds.add("hawk"); // [hawk] 17: System.out.println(birds.size()); // 1 18: birds.set(0, "robin"); // [robin] 19: System.out.println(birds.size()); // 1 20: birds.set(1, "robin"); // IndexOutOfBoundsException
5.2.4. clear()
void clear()
eg.
List<String> birds = new ArrayList<>(); birds.add("hawk"); // [hawk] birds.add("hawk"); // [hawk, hawk] System.out.println(birds.isEmpty()); // false System.out.println(birds.size()); // 2 birds.clear(); // [] System.out.println(birds.isEmpty()); // true System.out.println(birds.size()); // 0
5.2.5. contains()
contains()会调用equals()来判断元素是否匹配。
boolean contains(Object object)
eg.
List<String> birds = new ArrayList<>(); birds.add("hawk"); // [hawk] System.out.println(birds.contains("hawk")); // true System.out.println(birds.contains("robin")); // false
String实现了equals(),所以上面的例子可以正常工作。
5.2.6. equals()
ArrayList实现了自己的equals(),可以用于判断两个ArrayList是否相同,即各个元素和元素的顺序均相同。
eg.
31: List<String> one = new ArrayList<>(); 32: List<String> two = new ArrayList<>(); 33: System.out.println(one.equals(two)); // true 34: one.add("a"); // [a] 35: System.out.println(one.equals(two)); // false 36: two.add("a"); // [a] 37: System.out.println(one.equals(two)); // true 38: one.add("b"); // [a,b] 39: two.add(0, "b"); // [b,a] 40: System.out.println(one.equals(two)); // false
5.3. Wrapper Classes
包装类及其构造方法如图1所示。
从String转化到包装类的方法如图2所示。
eg.
int primitive = Integer.parseInt("123"); Integer wrapper = Integer.valueOf("123"); int bad1 = Integer.parseInt("a"); // throws NumberFormatException Integer bad2 = Integer.valueOf("123.45"); // throws NumberFormatException
5.4. Autoboxing
Java 5中引入了自动封装机制,将基本类型自动转换为相对应的包装类。
eg.
4: List<Double> weights = new ArrayList<>(); 5: weights.add(50.5); // [50.5] 6: weights.add(new Double(60)); // [50.5, 60.0] 7: weights.remove(50.5); // [60.0] 8: double first = weights.get(0); // 60.0
第8行自动将Double拆箱(unbox)为double。对null进行unbox,会抛出NullPointerException。
eg.
3: List<Integer> heights = new ArrayList<>(); 4: heights.add(null); 5: int h = heights.get(0); // NullPointerException
eg. 需要注意自动封装为Integer的情况:
List<Integer> numbers = new ArrayList<>(); numbers.add(1); numbers.add(2); // [1, 2] numbers.add(3); // [1, 2] numbers.remove(1); System.out.println(numbers); // [1, 3] numbers.remove(new Integer(1)); System.out.println(numbers); // [3]
remove() 有接受int参数的版本,这里remove() 的参数1没有自动封装为Integer,remove(1) 移除了下标为1的元素(2),而不是移除元素1;numbers.remove(new Integer(1)) 显式地进行封装,移除了元素1。
5.5. Converting Between array and List
从List转换为数组可以使用toArray() 。
eg.
3: List<String> list = new ArrayList<>(); 4: list.add("hawk"); 5: list.add("robin"); 6: Object[] objectArray = list.toArray(); 7: System.out.println(objectArray.length); // 2 8: String[] stringArray = list.toArray(new String[0]); 9: System.out.println(stringArray.length); // 2
第8行指明了新数组的大小为0,不够存储objectArray中的两个元素,于是自动生成了新的数组。
使用asList() 可以将数组转换为List,需要注意新生成的List与原始数组所使用的数据是相同的,对他们的修改会相互影响;且新生成的List和长度固定(和原始数组相同),不能使用add() 或remove() 来修改。
eg.
20: String[] array = { "hawk", "robin" }; // [hawk, robin] 21: List<String> list = Arrays.asList(array); // returns fixed size list 22: System.out.println(list.size()); // 2 23: list.set(1, "test"); // [hawk, test] 24: array[0] = "new"; // [new, test] 25: for (String b : array) System.out.print(b + " "); // new test 26: list.remove(1); // throws UnsupportedOperation Exception
通过asList() 得到的是一个固定长度的列表,使用add() 或remove() 尝试进行修改会得到UnsupportedOperation Exception。PS. 如果想要用remove()修改由数组转换的列表,可以使用:
List<String> list = new LinkedList<String>(Arrays.asList(split));
LinkedList提供了更快的remove() 方法。
asList()接受可变参数。
eg.
List<String> list = Arrays.asList("one", "two");
6. Working with Dates and Times
Java 8中引入了全新的日期和时间类,对比如图3所示。