Java API 所提供的用于在程序中存放对象的一系列类的实例。
数组其实也是一种容器, 不过其他容器类都不用也不能指定大小。
int size(); boolean isEmpty();
boolean contains(E element)//依据equals, add(...), remove(...); void clear();
boolean containsAll(Collection c), addAll(...), removeAll(...), retainAll(...)//保留交集;
E[] toArray(); Iterator<E> iterator();
import java.util.*; ... Collection c = new ArrayList(); // 父接口引用子类对象 // 可以存入不同类型的对象,但必须是对象,因为基本数据类型位于Stack里随时可被清空 c.add("Hello"); c.add(new Name("f1", "l1")); c.add(new Integer(200)); System.out.println(c.size()); System.out.println(c); // ArrayList的toString()方法 ... /** 输出: * 3 * [hello, fi1 l1, 100] */
所有实现了 Collection 接口的容器类都有一个 iterator() 方法用以返回一个实现了 Iterator 接口的对象;
Iterator 对象称作迭代器,用以方便地实现对容器内元素的遍历操作;
Iterator 接口内定义了三个方法:
boolean hasNext(); E next();
void remove(); // 删除指针前一个元素,(一定有机制保存了前一个元素的引用)所以在执行完 next() 之后只能 remove() 一次(那个保存前一个的引用删掉失效了)。Iterator的remove() 是在迭代过程中删除容器元素(不只是迭代器里的元素)的唯一安全方法,此时不能用容器类提供的remove,会产生例外,因为Iterator对象内部对容器对象做了线程锁定。
缺陷:1. 不适用数组 —— 不能方便地访问下标
2. 对于集合 —— 该for结构内部也是调用Iterator,但与Iterator相比却不能方便地删除集合中的元素(原因在上文)
结论:除了简单遍历读取元素外,不建议使用
对应数学中的“集合”概念
无序,无重复
HashSet,TreeSet 等
Tips:Set 和 List 类都具有以 Collection接口类 为参数的构造方法
有序,可有重复
像数组 —— 元素对应整型的索引,可按索引访问;又不同于数组 —— 不限大小,自动扩容
ArrayList,LinkedList 等
get(index); remove(index);
indexOf(E), lastIndexOf(...);
E set(index, element); void add(index, element)
void sort(List) // 借助于Comparable接口; void shuffle(List); void reverse(List); void filll(List, E); void copy(List dest, List src); int binarySearch(List, E) // 先排序再查找
所有可“排序”的类都实现了 java.lang.Comparable接口
只包含一个方法:public int compareTo(T o); 0: ==, +: this > obj, -: <。
Comparable接口的实现类通过实现 compareTo 方法确定该类对象的排序依据。Note: 实现该方法同重写equals()一样,要先检查类型, SDK1.5引进泛型后就不用了
class Name implements Comparable { ... ... public int compareTo(Object o) { // 强调:实现/重写的方法头部要copy自接口/父类 Name n = (Name) o; // 类型检查或强制转换 int lastCmp = lastName.compareTo(n.lastName); return (lastCmp != 0 ? lastCmp : firstName.compareTo(n.firstName)); } }
看应用
Array 读快改慢;
Linked 改快读慢;
Hash 两者之间。
键-值对, key和value都是对象
以Key标识,key不可重复,依据 hashCode 比较
HashMap类(Hash表实现),TreeMap类(红黑树)
V put(K key, V value); // 如果发生了替换,返回旧的value
V get(key), V remove(key); // value对象以Object类型输出,所以要再按原有类型强制转换
boolean containsKey(key), containsValue(value);
int size(); boolean isEmpty(); void clear();
void putAll(Map<K, V> t);
基础数据类型<->封装类 自动转换(JDK1.5后)
import java.util.* ... Map m1 = new HashMap(); m1.put("one", 1); // 并不是存在 put(Object, int) 方法,而是自动打包机制将int转换成Integer传给put方法 int i = (Integer) m1.get("one"); // Integer类型的对象可以自动解包成int,但是这里是以Object类型输出的,不强制转换成Integer型就不会启用自动解包机制 ...
起因:JDK1.4 以前类型不明确
解决办法:在定义集合的时候同时定义集合中对象的类型
格式:Collection<E>, Iterator<E>, Comparator<T> , Map<K, V>等凡是API中这样定义的接口、类;
使用:把指定的类型填进<>,见TestArgsWords.zip
优点:增强程序的可读性和稳定性