目录html
编程时,经常须要集中存放多个数据。能够使用数组来保存,但一旦初始化时指定了数组的长度,数组就不可变了。而集合类就很好的解决了这一问题。Java集合大体可分为 Set、List、Queue、Map四种体系。Java集合框架图:
【简图】
java
注:顺序分为 天然排序[a-z], 添加元素的排序shell
Collection接口是 List、Set和 Queue 接口的父接口编程
迭代器: Enumeration<E>
接口被 Iterator <E>
替代。它的实现类StringTokenizer数组
Enumeration e = new StringTokenizer("A-B-C","-"); while(e.hasMoreElements()){ // 是否还有元素 System.out.println(e.nextElement()); //返回下一个元素 } // Arrays.asList(T...a)返回的是一个T List<T> 类型的new ArrayList<>(a)对象 // 这个ArrayList<E> 是定义在Arrays中的私有类部类,且有一个带 E[] a 参数 Collection c = Arrays.asList("a","n","b"); Iterator it = c.iterator(); for( ;it.hasNext();) System.out.println(it.next());
List l = Arrays.asList("a","n","b"); ListIterator lit = l.listIterator(); while(lit.hasNext()){ System.out.println(lit.next()); } while(lit.hasPrevious()){ System.out.println(lit.previous()); } // foreach 是经过迭代器来实现 for (Object aL : l) { System.out.println(aL); }
List
List是一个有序可重复的集合,经常使用的List实现类 ArrayList, LinkedList和Vector。List接口实现类在实现插入元素时,都会根据索引进行排列,会改变其余元素的位置。安全
AbstractList
继承 AbstractCollection 抽象类,实现了 List 接口 ,是 ArrayList 和 AbstractSequentiaList 的父类。AbstractList 内部已经提供了 Iterator, ListIterator 迭代器的实现类Itr ,ListItr。多线程
ArrayList、LinkedList、Vectororacle
1-- ArrayList 使用数组方式存储数据(本质上是一个数组),y有初始容量大小 ,超容时自动扩容为原来的1.5倍。线程是不安全的。增删效率低,查询效率高。
防止不一样步访问列表:List list = Collections.synchronizedList(new ArrayList(...));
框架
ArrayList<String> al = new ArrayList<String>(5); //指定容量大小 al.ensureCapacity(10); // 增长容量 al.add("Hello"); // 元素可重复 al.add("Hello"); al.add("word"); al.set(1, "Two"); // 替换索引为1 的元素 al.add("four"); al.trimToSize(); al.remove(3); // 删除索引为 3 的元素 System.out.println(al.toArray().length); System.out.println(al.size()); //3 元素个数 System.out.println(al.get(1)); //Two 获取 index=0 的元素 //System.out.println(al.get(3)); // index=3 的元素被删除,报错
2-- LinkedList双向链表,实现了List和 Deque接口。与ArrayList同样也是线程不安全。双向链表,不存在元素限制,没有扩容机制。其查询效率差,增删效率高。dom
LinkedList<String> ll = new LinkedList<String>(); ll.add("adb"); // 元素可重复 ll.add("adb"); ll.add(1," "); // 内部经过遍历删除ll.remove(" "); ll.add("shell"); ll.addFirst("<"); // 列表开头插入指定的元素 对应的删除 ll.removeFirst(); ll.addLast(">"); // 列表结尾插入指定的元素 对应的删除 ll.removeLast(); ll.remove(3); // 删除 index=3 的元素 for(Object l: ll){ System.out.print(l); // <adb shell> 遍历输出列表元素 // ll.listIterator(); // 正向迭代 //ll.descendingIterator(); // 反向迭代 } ll.push("shell"); //实质上就是将元素插入到开头位置 addFirst() System.out.println("\n"+ll.get(0)); // 内部经过遍历查找 index=0 的元素 或者 ll.getFirst(); System.out.println(ll.element()); // 内部调用 getFirst() System.out.println(ll.pop()); // 内部调用 removeFirst() ll.clear(); // 清除列表全部元素
3-- Vector类实现了可扩展的对象数组,与ArrayList同样有初始容量大小,超容会自动扩容为原来的2倍,但线程是安全的。因此增删查询效率比ArrayList差一些。
Vector<Integer> v = new Vector<Integer>(); // Vector 继承AbstractCollection 重写的 toString() 方法 System.out.println(v); // 打印[] 与 ArrayList 同样 v.add(1); v.addElement(2); v.insertElementAt(129, 1); for(Object o: v) System.out.println(o); // 1 \n 129 \n 4 迭代 Vector 中的元素 //v.setSize(19);// 设置元素个数的大小 //System.out.println(v.capacity()); // 20 v.trimToSize(); //将容量大小变为所包含元素个数大小 System.out.println(v.capacity()); // 3 当前列表的容量大小 v.clear(); if(v.isEmpty()) System.out.println("none ");
Map 接口
Map将键映射到值的对象,不能包含重复的键。Map 中元素的顺序取决于迭代器迭代时的顺序,有的实现类(TreeMap)保证了元素输入输出时的顺序,有的实现类(HashMap)则是无序的 .
AbstractMap 抽象类
AbstractMap 提供了 Map 的基本实现。该抽象类中只有一个抽象方法public abstract Set<Entry<K,V>> entrySet();
HashMap、TreeMap、 HashTable
1-- HashMap 采用哈希表实现的键值对集合,底层实现链表数组(jdk1.8加入红黑树).有默认初始容量,扩容由容量和加载因子(0.75)决定。非线程安全的。
HashMap<String, String> m = new HashMap<String, String>(); m.put("1","zzz"); // key不能重复,value能够 m.put("2","zzz"); m.put("0",""); m.put(null,"111"); // 不打印该键值,被最后为null的键覆盖 m.put("4",null); m.put(null,null); // key,value容许空值 Set<String> s =m.keySet(); for(Object o: s){ // 迭代输出 map中的 keys System.out.println("key:" + o); } Collection c = m.values(); for(Object o: c){ // 迭代输出 map中的 values System.out.println("value:" + o); } // 迭代map for(Map.Entry<String, String> entry: m.entrySet()){ System.out.println(entry.getKey()+"--->"+entry.getValue()); }
2-- TreeMap 基于红黑树实现,按天然顺序或自定义顺序遍历键(key),键不能为null, 非线程安全
TreeMap<String, String> tm = new TreeMap<String, String>(); tm.put("1","22"); //tm.put(null,null); // 键不能为null, 会抛出空指针异常 tm.put("",""); tm.put("2",null); tm.put("0","22"); System.out.println(tm.replace("","1"));// 替换对应key的值 for(Map.Entry<String, String> entry: tm.entrySet()){ System.out.println(entry.getKey()+"--->"+entry.getValue()); } System.out.println("value:"+tm.get("")); // 经过key获取 value System.out.println("first key:" +tm.firstKey() +" ,value:"+ tm.lastKey()); // 获取第一个key - value System.out.println(tm.higherKey("2")); //大于给定键的小键,不存在则返回 null System.out.println(tm.tailMap("0")); // 返回其键大于等于 key的键值 System.out.println(tm.ceilingKey("2")); //大于或等于给定键的键 System.out.println(tm.lowerKey("2")); // 小于给定键的最大键,若是没有则返回 nul
3-- HashTable是散列表,继承Dictionary抽象类直接实现了Map接口。键和值都不能为 null,线程安全
Hashtable<String, String> ht = new Hashtable<String, String>(); ht.put("",""); //ht.put(null,""); // 键不能为 null //ht.put("1",null); // 值也不能为 null ht.put("1","a"); ht.put("2","b"); ht.put("0","c"); ht.put("3","d"); Enumeration e = ht.elements();//能够使用Enumeration 迭代器 for(Map.Entry<String, String> entry: ht.entrySet()){ System.out.println(entry.getKey()+"--->"+entry.getValue()); }
Set 接口
Set是一个不可重复的集合,容许包含值为null的元素。
AbstractSet 抽象类
继承 AbstractCollection 抽象类,实现了 Set 接口。与AbstractList 不一样,AbstractSet类中只有3 个方法 equals、hashCode、removeAll。其add,remove,clear ... 都是子类本身实现。
HashSet、TreeSet
1-- HashSet继承AbstractSet抽象类,直接实现了Set接口。无序列集合,而且多线程不安全。底层经过HashMap实现,Map中key不能重复,这也就是Set不容许重复的缘由。
HashSet<String> hs = new HashSet<String>(); String str = new String("abc"); hs.add(null); hs.add("abc"); hs.add(str); // 重复元素 hs.add(""); System.out.println(hs.size()); // 3 元素个数 // forEach 内部经过 for(T t:this){} 实现,调用的是Iterable接口(即 Collection接口的父类)中的方法, hs.forEach(System.out::println); // 等同于 o -> System.out.println(o) hs.removeAll(hs); // 调用父类的方法删除全部元素 hs.addAll(Arrays.asList("a","a","b")); // 将指定集合中的全部元素添加到此集合,可用于去重
2-- TreeSet继承AbstractSet抽象类,实现NavigableSet接口,而该接口继承了SortedSet最后才继承Set接口。使用元素的天然顺序对元素进行排序,或者根据建立 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。
TreeSet<String> ts = new TreeSet<String>(); ts.add("aaa0"); // 迭代时,按天然排序输出 [1, 2, 3, 4, aaa, aaa0, begin, end] ts.add("aaa"); ts.add("begin"); ts.add("1"); ts.add("2"); ts.add("3"); ts.add("4"); ts.add("end"); for(Object o: ts) System.out.println(o); System.out.println("\n"+ts.first()); // 1 返回集合中第一个元素 返回最后元素:ts.last() System.out.println(ts.subSet("a","b")); // [aaa, aaa0] 返回范围内部分元素 System.out.println(ts.tailSet("0")); // 返回大于或等于某元素的全部元素 System.out.println(ts.headSet("3")); // 返回小于某元素的全部元素
Queue接口
Queue 继承自 Collection 接口 ,Deque, LinkedList, PriorityQueue, BlockingQueue 等类都实现了它。队列一般但不必定是以FIFO(先进先出)方式排序元素。
Deque接口
双向队列(Deque),是Queue的一个子接口,双向队列是指该队列两端的元素既能入队(offer)也能出队(poll).它的实现类:ArrayDeque。
PriorityQueue、ArrayDeque
1-- PriorityQueue继承AbstractQueue抽象类,抽象类继承AbstractCollection抽象类实现了Queue接口,优先队列不容许null元素,且非线程安全的。其容器是一个object的数组。默认状况下采用的是天然排序,取出的是队列最小的元素。
Collection c = Arrays.asList("a","b","c"); PriorityQueue<String> pq = new PriorityQueue<String>(c); pq.offer("0"); // 指定的元素插入到此优先级队列 //pq.offer(null); // 不容许插入null // pq.add(null); // 调用 offer方法插入元素 pq.offer("a"); // 容许重复的值 System.out.println(pq.remove("v"));// false 从该队列中删除指定元素的单个实例(若是存在) System.out.println(pq.peek()); // 检索但不删除此队列的头,不存在则返回null System.out.println(pq.poll()); // 检索并删除此队列的头,不存在则返回null System.out.println(pq.size()); System.out.println(pq); // [a, a, c, b] for(Object o : pq){ System.out.println(o); // 遍历队列中的元素 }
2--ArrayDeque 继承了AbsrtactCollection抽象类,实现了Deque接口。因此ArrayDeque拥有二者的特性。因为是两端队列,因此其顺序是按照元素插入数组中对应位置产生的。
Collection c = Arrays.asList("a","b","c"); ArrayDeque<String> aq = new ArrayDeque<String>(c); aq.addFirst("start"); // 头部插入指定元素 等同于offerFirst aq.addLast("end"); // 尾部插入指定元素 等同于offerLast //aq.add(null); // 不容许插入null aq.add("0"); // 末尾插入指定的元素, 调用addLast System.out.println(aq); System.out.println(aq.getFirst()); // start 检索但不删除,这个deque的第一个元素 System.out.println(aq.getLast()); // 0 检索但不删除,这个deque的最后一个元素 aq.offer("in"); // 调用 offerLast 再调用 addLast.实质与add同样。 System.out.println(aq.pop()); // 删除第一个元素 调用 removeFirst 再调用 pollFirst System.out.println(aq.poll()); // 删除第一个元素 调用 pollFirst aq.push("me"); // 将元素推到第一个位置 调用 addFirst System.out.println(aq);
Collections该工具类提供了大量方法对集合进行排序、查询和修改等操做,还提供了将集合对象置为不可变、对集合对象实现同步控制等方法。
Arrays 工具类提供了将数组转换为集合的方法 Arrays.asList().
List<String> l = Arrays.asList("a","b","c","d","e","f"); // 对列表中的元素进行翻转 Collections.reverse(l); System.out.println(l); // [f, e, d, c, b, a] //l.add("1"); 会抛出异常java.lang.UnsupportedOperationException,Arrays.asList()返回的是其内部类的 new ArrayList()对象 // 而其内部类没有重写 AbstractList中的add方法,因此调用的是父类的add,而父类的add方法直接抛出异常 List<String> nl = new ArrayList<>(l); nl.add("0"); // 对列表默认顺序(天然顺序)进行排序 Collections.sort(nl); System.out.println(nl); // [0, a, b, c, d, e, f] nl.add("aa"); // 根据其元素的 天然顺序返回给定集合的最大\小元素 System.out.println( Collections.max(l)); // f System.out.println( Collections.min(l)); // a System.out.println(nl); // [0, a, b, c, d, e, f, aa] // 使用指定的随机源随机排列指定的列表 Collections.shuffle(nl, new Random()); // 不带种子的随机数,每次都不同。反之,每次都同样 System.out.println(nl); // [b, aa, f, d, 0, c, a, e] // 若是两个指定的集合没有共同的元素,则返回 true System.out.println(Collections.disjoint(l, nl));
注:
http://www.trinea.cn/category/java/
http://www.cnblogs.com/midiyu/p/8145503.html
http://www.benchresources.net/java/collection-framework/
https://blog.csdn.net/u011240877/article/category/6447444
https://docs.oracle.com/javase/tutorial/collections/interfaces/collection.html