集合(容器)—Collection和Map两大体系浅谈

特点:1. 集合类也叫做容器类,和数组一样,用于存储数据,但数组类型单一,并且长度固定,限制性很大,而集合类可以动态增加长度;

           2. 集合存储的元素都是对象(引用地址),所以集合可以存储不同的数据类型,但如果是需要比较元素来排序的集合,则需要类型一致;

   3. 集合中提供了统一的增删改查方法,使用方便;

      4. 支持泛型,避免数据不一致和转换异常,还对常用的数据结构进行了封装。

结构:集合框架体系是由CollectionMap(映射关系)和Iterator(迭代器)组成,下面只说常用,并非全部

注1:Map里面的键值对虽然没强调是否可重复,但是记住,Key是唯一的,但是Value可以重复,所以存在一个Value对应多个Key的状况;

1 public class Test {
2     public static void main(String[] args) {
3         // HashMap在初始化时,尽量确定大小,符合规范  
4         HashMap<Integer, String> map = new HashMap<Integer, String>(16);
5         map.put(1, "张三");
6         map.put(2, "张三");
7         map.put(3, "李四");
8     }
9 }
View Code

一、Collection架构源码观察及应用

  1. 在Collection的结构中,声明了一些通用的方法,下面介绍常用的:  

 1          * boolean add(E e)-------------------->添加指定元素
 2          * boolean addAll(Collection c)---------------->将指定集合中所有元素都添加到此 collection
 3          * boolean contains(Object o)-------------------->集合中是否包含了指定元素
 4          * boolean containsAll(Collection<?> c)------------>该集合是否包含指定集合中所有元素
 5          * boolean remove(Object o)--------------------------->移除指定元素
 6          * boolean removeAll(Collection<?> c)-------------->移除指定的collection参数的所有元素
 7          * void clear()----------------------------------->清除集合中所有元素
 8          * boolean retainAll(Collection<?> c)-------------------->保留指定Collection参数中元素,是两个集合的元素交集
 9          * boolean equals(Object o)-------------------->比较此 collection 与指定对象是否相等
10          * boolean isEmpty()-------------------->判断该集合是否为空
11          * Iterator<E> iterator()-------------------->返回此 collection 的迭代器,用来遍历元素
12          * int hashCode()-------------------->返回集合的哈希码值
13          * int size()-------------------->返回此 collection 中的元素数
14          * Object[] toArray()-------------------->返回一个包含该Collection所有元素的对象数组
15          * <T> T[] toArray(T[] a)-------------------->返回一个包含该Collection所有元素的数组,数组类型和指定数组的类型一致
View Code

    2. 声明方式:

  Set类

 1     public static void main(String[] args) {
 2 
 3         /**
 4          * Set类:
 5          * 不允许重复对象
 6          * 无序容器,你无法保证每个元素的存储顺序,TreeSet通过Comparator或者 Comparable维护了一个排序顺序。
 7          * 只允许一个 null 元素
 8          * Set接口最流行的几个实现类是HashSet、LinkedHashSet以及TreeSet。最流行的是基于HashMap实现的HashSet;
 9          * TreeSet还实现了SortedSet接口,因此TreeSet 是一个根据其compare()和compareTo()的定义进行排序的有序容器。
10          */
11         HashSet<String> hashSet = new HashSet<String>();
12         LinkedHashSet<String> linkedHashSet = new LinkedHashSet<String>();
13         TreeSet<String> treeSet = new TreeSet<String>();
14 
15         // 另一种写法, 不过推荐第一种写法,他两本质差不多
16         Set<String> hashSet1 = new HashSet<String>();
17         Set<String> linkedHashSet1 = new LinkedHashSet<String>();
18         Set<String> treeSet1 = new TreeSet<String>();
19 
20         // 验证TreeSet的有序性
21         for (int i = 0; i < 100; i++) {
22             hashSet.add(""+i);
23         }
24         System.out.println(hashSet);
25         // 输出: [88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 10, 98, 11, 99, 12...
26         treeSet.addAll(hashSet);
27         System.out.println(treeSet);
28         // 输出: [0, 1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 2, 20, 21, 22, 23, 24, 25, 26...
29     }
View Code

  List类:

 1     public static void main(String[] args) {
 2         /**
 3          * Arraylist:
 4          * 优点:ArrayList是实现了基于动态数组的数据结构,因为地址连续,一旦数据存储好了,查询操作效率会比较高(在内存里是连着放的)。
 5          * 缺点:因为地址连续, ArrayList要移动数据,所以插入和删除操作效率比较低。
 6          *
 7          * LinkedList:
 8          * 优点:LinkedList基于链表的数据结构,地址是任意的,所以在开辟内存空间的时候不需要等一个连续的地址,
 9          * 对于新增和删除操作add和remove,LinedList比较占优势。LinkedList 适用于要头尾操作或插入指定位置的场景
10          * 缺点:因为LinkedList要移动指针,所以查询操作性能比较低。
11          */
12         ArrayList<Integer> arrayList = new ArrayList<Integer>();
13         LinkedList<Integer> linkedList = new LinkedList<Integer>();
14     }
View Code

  3. 方法的简单运用

 1     public static void main(String[] args) {
 2 
 3 
 4         /**
 5          * boolean add(E e)-------------------->添加指定元素
 6          * boolean addAll(Collection c)---------------->将指定集合中所有元素都添加到此 collection
 7          * boolean contains(Object o)-------------------->集合中是否包含了指定元素
 8          * boolean containsAll(Collection<?> c)------------>该集合是否包含指定集合中所有元素
 9          * boolean remove(Object o)--------------------------->移除指定元素
10          * boolean removeAll(Collection<?> c)-------------->移除指定的collection参数的所有元素
11          * void clear()----------------------------------->清除集合中所有元素
12          * boolean retainAll(Collection<?> c)-------------------->保留指定Collection参数中元素,是两个集合的元素交集
13          * boolean equals(Object o)-------------------->比较此 collection 与指定对象是否相等
14          * boolean isEmpty()-------------------->判断该集合是否为空
15          * Iterator<E> iterator()-------------------->返回此 collection 的迭代器,用来遍历元素
16          * int hashCode()-------------------->返回集合的哈希码值
17          * int size()-------------------->返回此 collection 中的元素数
18          * Object[] toArray()-------------------->返回一个包含该Collection所有元素的对象数组
19          * <T> T[] toArray(T[] a)-------------------->返回一个包含该Collection所有元素的数组,数组类型和指定数组的类型一致
20          */
21 
22 
23         HashSet<String> hashSet = new HashSet<String>();
24         for (int i = 0; i < 100; i++) {
25             hashSet.add(""+i);
26         }
27         System.out.println("hashSet:" + hashSet);
28         //输出:[88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 10, 98, 11, 99, 12...,可以看见HashSet的无序的
29 
30         System.out.println("hashSet.size(): "+hashSet.size());
31         System.out.println("hashSet.hashCode(): "+hashSet.hashCode());
32         // 输出: hashSet.hashCode(): 153120
33 
34         HashSet<String> hashSet1 = new HashSet<String>();
35         hashSet1.addAll(hashSet);
36         System.out.println("hashSet1.addAll(hashSet): " + hashSet1);
37 
38         System.out.println("hashSet.equals(hashSet1): "+hashSet.equals(hashSet1));
39 
40         hashSet1.removeAll(hashSet);
41         System.out.println("hashSet1.removeAll(hashSet): " + hashSet1);
42 
43         hashSet.clear();
44         System.out.println("hashSet.clear(): " + hashSet);
45 
46         System.out.println("hashSet.isEmpty(): "+hashSet.isEmpty());
47     }
48     /**
49      * 结果:
50      * hashSet:[88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 10, 98, 11, 99, 12, 13, 14, 15,...
51      * hashSet.size(): 100
52      * hashSet.hashCode(): 153120
53      * hashSet1.addAll(hashSet): [88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 10, 98, 11,, ...
54      * hashSet.equals(hashSet1): true
55      * hashSet1.removeAll(hashSet): []
56      * hashSet.clear(): []
57      * hashSet.isEmpty(): true
58      */
View Code

二、Map架构源码观察及应用

  1. 声明方式及其使用环境

 1     public static void main(String[] args) {
 2 
 3         /**
 4          * HashMap非线程安全,基于哈希表实现。使用HashMap要求添加的键类明确定义了hashCode()和equals()[可以重写hashCode()和equals()],
 5          * 为了优化HashMap空间的使用,您可以调优初始容量和负载因子。
 6          * TreeMap非线程安全,基于红黑树实现。TreeMap没有调优选项,因为该树总处于平衡状态。
 7          *
 8          * 适用场景分析:
 9          * 1)、HashMap和HashTable区别
10          * HashMap去掉了HashTable的contains方法,但是加上了containsValue()和containsKey()方法。
11          * HashTable是同步的,而HashMap是非同步的,效率上比HashTable要高。
12          * HashMap允许空键值,而HashTable不允许。
13          *
14          * 2)、HashMap和Treemap区别
15          * HashMap适用于Map中插入、删除和定位元素。
16          * Treemap:适用于按自然顺序或自定义顺序遍历键(key)。
17          */
18         HashMap<Integer, String> hashMap = new HashMap<Integer, String>(16);
19         TreeMap<String, String> treeMap = new TreeMap<String, String>();
20         LinkedHashMap<Integer, String> linkedHashMap = new LinkedHashMap<Integer, String>();
21     }
View Code

  2. 常用方法及其简单应用

 1     public static void main(String[] args) {
 2         /**
 3          *  boolean containsKey(Object key)----------------->该映射是否包含指定键值
 4          *  boolean containsValue(Object value)----------------->如果该键值对中有一个或多个key射到指定值,则返回 true
 5          *  Set<Map.Entry<K,V>> entrySet()----------------->返回此映射中包含的映射关系的 Set 视图。
 6          *  Set<K> keySet()----------------->返回此映射中所有键的 Set 视图。
 7          *  Collection<V> values()----------------->返回一个此映射中包含的值的 Collection
 8          *  V get(Object key)----------------->返回指定键映射的值。如果不存在,则返回 null
 9          *  V put(K key, V value)----------------->放入一个键值对(key-value)
10          *  void putAll(Map<? extends K,? extends V> m)----------------->把指定映射的所有映射关系复制到此映射中
11          *  boolean isEmpty()----------------->如果此映射未包含键值映射关系,则返回 true
12          *  boolean equals(Object o)----------------->比较指定的对象与此映射是否相等
13          *  int size()----------------->返回此映射中的键-值映射关系数
14          *  int hashCode()----------------->返回此映射的哈希码值
15          */
16 
17         HashMap<Integer, String> hashMap = new HashMap<Integer, String>(16);
18         TreeMap<Integer, String> treeMap = new TreeMap<Integer, String>();
19         LinkedHashMap<Integer, String> linkedHashMap = new LinkedHashMap<Integer, String>();
20 
21         for (int i = 1; i <= 10; i++) {
22             hashMap.put(i, "第" + i + "个键对应的值");
23         }
24 
25         //第一种:普遍使用,二次取值
26         System.out.println("通过Map.keySet遍历key和value:");
27         for (Integer key : hashMap.keySet()) {
28             System.out.println("key= "+ key + " and value= " + hashMap.get(key));
29         }
30 
31         //第二种
32         System.out.println("通过Map.entrySet使用iterator遍历key和value:");
33         Iterator<Map.Entry<Integer, String>> it = hashMap.entrySet().iterator();
34         while (it.hasNext()) {
35             Map.Entry<Integer, String> entry = it.next();
36             System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
37         }
38 
39         //第三种:推荐,尤其是容量大时</span>
40         System.out.println("通过Map.entrySet遍历key和value");
41         for (Map.Entry<Integer, String> entry : hashMap.entrySet()) {
42             System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
43         }
44 
45         //第四种
46         System.out.println("通过Map.values()遍历所有的value,但不能遍历key");
47         for (String v : hashMap.values()) {
48             System.out.println("value= " + v);
49         }
50 
51         System.out.println(hashMap.containsKey(1));   // true
52         System.out.println(hashMap.containsValue("第1个键对应的值"));   // true
53         System.out.println(hashMap.get(1));    // 第1个键对应的值
54 
55         HashMap<Integer, String> hashMap1 = new HashMap<Integer, String>();
56         hashMap1.putAll(hashMap);
57         System.out.println(hashMap.equals(hashMap1));   // true
58 
59         treeMap.putAll(hashMap);
60 
61         for (Map.Entry<Integer, String> entry : treeMap.entrySet()) {
62             System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
63         }
64 
65         System.out.println(treeMap.isEmpty());  // false
66         System.out.println(treeMap.size());
67     }
View Code

注2 : 

/**
* 什么场景下使用list,set,map呢?
* 1. 如果你经常会使用索引来对容器中的元素进行访问,那么List是你的正确的选择。如果你已经知道索引了的话,
* 那么List的实现类比如ArrayList可以提供更快速的访问,如果经常添加删除元素的,那么肯定要选择LinkedList。
*
* 2. 如果你想容器中的元素能够按照它们插入的次序进行有序存储,那么还是List,因为List是一个有序容器,它按照插入顺序进行存储。
*
* 3. 如果你想保证插入元素的唯一性,也就是你不想有重复值的出现,那么可以选择一个Set的实现类,
* 比如 HashSet、LinkedHashSet或者TreeSet。所有Set的实现类都遵循了统一约束比如唯一性,而且还提供了额外的特性:
* 比如TreeSet还是一个SortedSet,所有存储于TreeSet中的元素可以使用Java里的Comparator或者Comparable进行排序。
* LinkedHashSet也按照元素的插入顺序对它们进行存储。
*
* 4. 如果你以键和值的形式进行数据存储那么 Map 是你正确的选择。你可以根据你的后续需要从 Hashtable、HashMap、TreeMap 中进行选择。
*/

    

   

猜你喜欢

转载自www.cnblogs.com/xpeanut/p/12893436.html
今日推荐