1. Java集合框架概述
1.1 集合和数组
- Java中对多个对象进行存储时,若使用Array则有很多弊端,而Java集合可以动态地把多个对象的引用放入容器中。
- 使用数组存储对象的弊端:① 一旦创建,长度不可变;② 数组中存放的对象个数不可知,需要自行设变量记录所存储对象的个数;③数组中提供的方法非常有限,对添加、删除、插入等操作非常不便,效率不高。
1.2 集合的分类
Java集合可分为Collection和Map两种体系,集合中存储基本数据类型时为包装类。
- Collection接口:单列数据,定义了存储一组对象的方法的集合。有List和Set等多种子接口。
- List接口:元素有序、可重复的集合。(又称作动态数组)
- Set接口:元素无序、不可重复的集合。
- Map接口:双列数据,保存具有映射关系的“key-value对”集合。
2. Collection接口方法
- add(Object e):添加元素e到集合中(对基本数据而言,e为包装类)
- size():获取集合中元素的个数
- addAll(Collection c):将集合c中所有元素添加到当前集合中
- isEmpty():判断当前集合是否为空
- clear():清空集合元素
- contains(Object e):判断当前集合中是否包含e,通过equals()方法进行判断
- containsAll(Collection c):判断集合c中的所有元素是否都在当前集合中
- remove(Object e):删除集合中的元素e,返回boolean类型
- removeAll(Collection c):从当前集合中移除集合c中的所有元素(两集合求差)
- retainAll(Collection c):两集合求交,返回当前集合
- equals(Collection c):判断两集合是否相同
- hashCode():返回当前集合的哈希值
- toArray():将集合转化为数组
- Arrays.asList(Array a):将数组a转为List
- iterator():返回一个Iterator接口的实例,用于遍历集合元素
3. Iterator迭代器接口
- 使用Iterator接口实现集合元素的遍历,Iterator对象成为迭代器,是设计模式中的一种。
- 迭代器模式提供一种方法访问一个容器对象中各个元素,而又不暴露该对象的内部细节。(类似于公交车售票员)
- Collection接口继承了java.lang.Iterator接口,该接口有一个iterator()方法。
- Iterator仅用于遍历集合,Iterator本身并没有承装对象的能力。如果需要创建Iterator对象,则必须有一个被迭代的集合。
- 集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标在集合的第一个元素之前。
Iterator<Object> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
- hasNext()方法判断指针下一处是否有元素
- next()方法将指针下移一位
- remove()方法删除集合中指针所指的元素(这是迭代器对象的remove方法,与集合中的remove方法不同)
foreach循环遍历集合或数组
Java 5.0提供了foreach循环(增强for循环)访问Collection和数组,内部使用Iterator循环。
for (Object e:list) {
System.out.println(e);
}
4. Collection子接口一:List
4.1 List的常用实现类
- 鉴于Java中数组存储数据的局限性,常用List替代数组
- List接口的常用实现类有:ArrayList、LinkedList、Vector
- ArrayList:作为List接口的主要实现类,线程不安全,效率高。底层使用Object[]数组存储,jdk7中,空参构造器初始化容量为10的数组,当数组容量不够时扩容为原来的1.5倍,建议使用带参构造器;jdk8中,空参构造器初始化不创建数组,当添加元素时才创建长度为10的数组,其他操作与jdk7相同。
- LinkedList:底层使用双向链表存储。对频繁的插入、删除操作效率高。内部声明了Node类型的first和last属性,默认值为null,添加元素时新建Node对象。
- Vector:为List的古老实现类,与ArrayList几乎相同,线程安全,效率低,已弃用。
4.2 List接口中的常用方法(比Collection接口新增)
- void add(int index, Object e):在index位置插入元素e
- boolean addAll(int index, Collection c):从index位置开始将集合c中所有元素添加进来
- Object get(int index):获取index位置的元素
- int indexOf(Object e):返回元素e在集合中首次出现的位置
- int lastIndexOf(Object e):返回元素e在集合中最后出现的位置
- Object remove(int index):移除index位置的元素,并返回该元素(与Collection中的remove方法构成重载)
- Object set(int index, Object e):设置index位置的元素为e
- List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置左闭右开的子集合
5. Collection子接口二:Set
Set接口没有提供额外的方法,Set集合不允许包含相同的元素,判断两个对象是否相同根据equals()方法。Set的无序性不等于随机性,遍历的时候也会按特定顺序。HashSet底层也是用数组存储数据,存储数据时并非按数组索引的顺序添加,而是根据数据的Hash值决定的。
5.1 HashSet
- HashSet是Set接口的典型实现,按Hash算法来存储集合中的元素,有很好的存取、查找、删除性能。
- HashSet的特点有:① 不能保证元素的排列顺序;② 线程不安全;③ 集合元素可以是null
- HashSet判断两个元素相等的标准:两个对象通过hashCode()方法比较相等,且两个对象的equals()方法返回值也相等。
- 存放在HashSet容器中的对象,对应的类一定要重写equals()和hashCode(Object e)方法,且这两个方法尽可能保持一致性。
- HashSet底层有数组+链表的结构。向HashSet中添加元素a时,首先调用a所在类的hashCode()方法,计算a的哈希值,此哈希值通过某种算法计算出在HashSet底层数组中的存放位置,判断该位置上是否已有元素。
- 若没有其他元素,则a添加成功;
- 若有其他元素b(或有以链表存储的多个元素b、c、…),则比较a与b的哈希值,若哈希值不相同,则a添加到该位置的链表末尾;
- 若哈希值不同,则调用a所在类的equals()方法,若返回true,则a添加失败;
- 若返回false,则a添加到该位置的链表末尾
5.2 LinkedHashSet
- LinkedHashSet是HashSet的子类,根据元素的hashCode值来决定元素的存储位置,同时使用双向链表维护元素的次序,这使得元素看起来是以插入顺序保存的,遍历时按照添加的顺序遍历。
- LinkedHashSet插入性能略低于HashSet,但在迭代访问元素时有很好的性能。
5.3 TreeSet
- TreeSet是SortedSet接口的实现类,TreeSet可以确保集合元素处于排序状态。
- TreeSet底层使用红黑树结构存储数据。
- TreeSet有两种排序方法:自然排序(Comparable)&定制排序(Comparator)。默认情况下使用自然排序。
TreeSet set = new TreeSet(com);
空参构造器创建的对象为自然排序,带参构造器传入一个Comparator对象为定制排序
- 向TreeSet中添加的数据,要求是相同类的对象,且该类的对象能够比较大小,不再用equals()方法比较是否相等,自然排序中使用compareTo()方法比较大小,定制排序使用compare()方法比较大小。
6. Map接口
4.1 Map的主要实现类
- HashMap:Map的主要实现类,线程不安全,效率高,可以存储null的key和value
- Hashtable:Map的古老实现类,线程安全,效率低,不能存储null的key和value
- LinkedHashMap:在原有的HashMap底层结构基础上,添加了一对指针,指向前一个和后一个元素。保证在遍历Map元素时,可以按添加的顺序实现遍历
- TreeMap:可以按照添加的key进行排序,实现排序遍历。底层使用红黑树
- Properties:常用来处理配置文件。key和value都是String类型
4.2 Map的key-value结构
- Map中的key:无序的、不可重复的,使用Set存储所有的key。要求key所在的类重写equals()和hashCode()方法(TreeMap要实现Comparable接口)
- Map中的value:无序的、可重复的,使用Collection存储所有的value。要求value所在的类重写equals()方法
- 一个key-value对构成了一个Entry对象,Map中的entry:无序的、不可重复的,使用Set存储所有的entry
4.3 HashMap的底层实现原理
- jdk7中HashMap底层使用数组+链表结构存储,jdk8中HashMap底层使用数组+链表+红黑树结构存储
- 在实例化后,jdk7底层创建了长度为16的一维Entry数组,默认临界因子0.75,
- 向HashMap中添加元素key0-value0时,计算key0的哈希值,得到在Entry数组中的存放位置
- 如果Entry数组存放位置上的数据为空,则key0-value0添加成功
- 如果Entry数组存放位置上的数据不为空,则比较key0与已存在数据key的哈希值,若都不相同,则key0-value0添加成功
- 若key0与某个数据key1的哈希值相同,继续比较key0与key1的equals()方法,若返回false,则key0-value0添加成功,以链表的方式存储;若返回true,则使用value0替换value1
- 在添加数据过程中,当min(Entry数组长度 - 1, 临界因子*Entry数组长度)<=数组中元素个数,且数组Entry当前位置存在元素时,若需要Entry数组扩容,则将长度扩展为之前的2倍,并将原有数据复制过来
- jdk8中实例化时并不创建数组,首次添加数据时才创建长度为16的Node数组,当数组某一个索引位置上的元素以链表形式存储的数据个数大于8,且当前Node数组长度大于64(否则扩容Node数组),则此时该索引位置上的所有数据改用红黑树存储
4.4 Map中的常用方法
- Object put(Object key, Object value):添加,返回被覆盖的value
- void putAll(Map m):全部添加
- Object remove(Object key):移除指定的键值对,返回value
- void clear():清空当前map中的所有数据
- Object get(Object key):获取指定key对应的value
- boolean containsKey(Object key):是否包含指定的key
- boolean containsValue(Object value):是否包含指定的value
- int size():返回map中键值对的个数
- boolean isEmpty():判断当前map是否为空
- boolean equals(Object e):判断当前map与e是否相等
- Set keySet():返回所有key构成的Set集合,用于遍历所有的key
- Collection values():返回所有value构成的Collection集合,用于遍历所有的value
- Set entrySet():返回所有键值对构成的Set集合,用于遍历所有的键值对
Set entrySet = map.entrySet();
Iterator iterator = entrySet.iterator();
while(iterator.hasNext()){
Object e = iterator.next();
Map.Entry entry = (Map.Entry) e;
System.out.println(entry.getKey() + ":" + entry.getValue());
}
4.5 Properties
存取数据时,建议使用setProperty(String key, String value)方法和getProperty(String key)方法
Properties properties = new Properties();
FileInputStream fileInputStream = new FileInputStream("jdbc.properties");
properties.load(fileInputStream);
String name = properties.getProperty("name");
String password = properties.getProperty("password");
System.out.println(name + ":" + password);
7. Collections工具类
Collections是一个操作Collection、Map的工具类,提供了一系列静态的方法对集合元素进行排序、查询、修改等操作,还提供了对集合对象设置不可变,对集合对象实现同步控制等方法。
7.1 排序操作(均为static方法)
- reverse(List):反转List中元素的顺序
- shuffle(List):对List集合元素进行随机排序
- sort(List):根据元素的自然顺序对指定List集合元素按升序排序
- sort(List, Comparator):根据Comparator指定的顺序对List元素排序
- swap(List, int, int):将LIst中的i处元素和j处元素进行交换
7.2 查找、替换
- Object max(Collection)
- Object max(Collection, Comparator)
- Object min(Collection)
- Object min(Collection, Comparator)
- int frequency(Collection, Object):返回指定集合中指定元素的出现次数
- void copy(List dest, LIst src):将src中的内容复制到dest中,要求dest中现有元素个数不少于src中的元素个数
- boolean replaceAll(LIst list, Object oldVal, Object newVal):使用新值替换List对象的所有旧值
7.3 同步控制
Collections类中提供了多个synchronizedXxx()方法,该方法可将指定集合包装成线程同步的集合,从而解决多线程并发访问集合时的线程安全问题。