OCA/OCP Java Note (7): Core Java APIs (2)

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所示。

图1

图1

 

  从String转化到包装类的方法如图2所示。

图2

图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所示。

图3

图3