一、概述

1.定义

1:集合本身就是一个容器,一个java对象,集合储存的是对象的内存地址。
2:在java中每一个不同的集合,底层会对应不同的数据结构。(往集合c1中放数
据,可能放到数组上了,往集合c2中放数据,可能放到二叉树上了。)
3:所有的集合类和集合接口都在java.util包下。
4:在java中集合分为两大类:
一类是单个方式储存元素:
单个方式储存元素,这一类集合中超级父接口:java.util.Collection;
一类是以键值对的方式储存元素:
以键值对的方式储存元素,这一类集合中超级父接口:java.util.map;
5:collection中能存放什么元素?
没有使用”泛型”之前,collection中可以存储Object的所有子类型。
使用了”泛型”之后,collection中只能存储某个具体的类型

Collection

集合概述 - 图3

1. Set(无序不可重复)

  • TreeSet:基于红黑树实现,支持有序性操作,例如根据一个范围查找元素的操作。但是查找效率不如 HashSet,HashSet 查找的时间复杂度为 O(1),TreeSet 则为 O(logN)。

解释:SortedSet集合存储元素的特点:由于继承了Set集合,所以它的特点也是无序不可重复,但是放在SortedSet集合中的元素可以自动排序我们成为可排序集合。放到该集合中的元素是自动按照大小顺序排序的

  • HashSet:基于哈希表实现,支持快速查找,但不支持有序性操作。并且失去了元素的插入顺序信息,也就是说使用 Iterator 遍历 HashSet 得到的结果是不确定的。
  • LinkedHashSet:具有 HashSet 的查找效率,并且内部使用双向链表维护元素的插入顺序。

    2. List(有序可重复)

  • ArrayList:基于动态数组实现,支持随机访问。

  • Vector:和 ArrayList 类似,但它是线程安全的。
  • LinkedList:基于双向链表实现,只能顺序访问,但是可以快速地在链表中间插入和删除元素。不仅如此,LinkedList 还可以用作栈、队列和双向队列。

    3. Queue

  • LinkedList:可以用它来实现双向队列。

  • PriorityQueue:基于堆结构实现,可以用它来实现优先队列。

    Map

    所有的Map的key都是无序不可重复
    集合概述 - 图4

  • TreeMap:基于红黑树实现。

  • HashMap:基于哈希表实现。
  • HashTable:和 HashMap 类似,但它是线程安全的,这意味着同一时刻多个线程同时写入 HashTable 不会导致数据不一致。它是遗留类,不应该去使用它,而是使用 ConcurrentHashMap 来支持线程安全,ConcurrentHashMap 的效率会更高,因为 ConcurrentHashMap 引入了分段锁。
  • LinkedHashMap:使用双向链表来维护元素的顺序,顺序为插入顺序或者最近最少使用(LRU)顺序。

总结-开发中如何选择

1.一组对象(Collection接口)

允许重复: List

增删多:LinkedList(底层双向链表)
改查多:ArrayList(底层数组)

不允许重复: Set

无序:HashSet(底层HashMap,既(数组+链表+红黑树)
排序:TreeSet
插入和取出顺序一致:LinkedHashSet(数组+双向链表)

2.一组键值对(Map)

键无序:HashMap
键排序:TreeMap
键插入和取出顺序一致:LinkedHashMap
读取文件:Properties

二、容器中的设计模式

迭代器模式

集合概述 - 图5
Collection 继承了 Iterable 接口,其中的 iterator() 方法能够产生一个 Iterator 对象,通过这个对象就可以迭代遍历 Collection 中的元素。

JDK 1.5 引入了增强的for循环,简化了迭代容器时的写法。
for (元素类型 变量名 : 数组或集合) {
System.out.println(变量名);
}

  1. //使用增强for迭代
  2. ArrayList<String> list = new ArrayList<String>();
  3. list.add(new String("Monday"));
  4. list.add(new String("Tuesday"));
  5. list.add(new String("Wensday"));
  6. for(String weekday : list){//enhanced for statement
  7. System.out.println(weekday.toUpperCase());
  8. }

迭代器iterator
在Map中不能用,在所有Collection以及子类中使用

  1. Collection c = new Arraylist();
  2. c.add("abc");
  3. c.add(123);
  4. c.add(new Object());
  5. //第一步:获取集合迭代器对象Iterator
  6. Iterator it = c.itrator();
  7. /*第二部:通过以上获取的迭代器对象开始迭代
  8. 以下两个方法是迭代器对象Iterator中的方法:
  9. boolean hasNext() 如果仍有对象可以迭代则返回 true
  10. Object next() 返回迭代的下一个元素
  11. */
  12. while(it.hasNext()){
  13. Object obj = it.next();
  14. System.out.println(obj);
  15. }
  16. }
  17. }

image.png

适配器模式

Arrays.asList()
该方法是将数组转化成List集合的方法。

  1. List<String> list = Arrays.asList("a","b","c");

(1)该方法不建议使用于基本数据类型的数组(byte,short,int,long,float,double,boolean),
该方法适用于对象型数据的数组(String、Integer…)
(2)不支持add()、remove()、clear()等方法
为什么不支持add()、remove()、clear()等方法???
这样是不行的

  1. String [] arr= new String[]{"张三","李四"};
  2. List<String> list = Arrays.asList(arr);
  3. //也可以这样写
  4. //List<String> list = Arrays.asList("张三","李四");
  5. list.add("王五");

异常如下:

  1. java.lang.UnsupportedOperationException
  2. at java.util.AbstractList.add(AbstractList.java:148)
  3. at java.util.AbstractList.add(AbstractList.java:108)
  4. at com.example.demo.ClassTest.test2(ClassTest.java:49)
  5. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  6. at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

为什么会这样呢,看下源码就很清楚了:

  1. public static <T> List<T> asList(T... a) {
  2. return new ArrayList<>(a);
  3. }
  4. /**
  5. * @serial include
  6. */
  7. private static class ArrayList<E> extends AbstractList<E>
  8. implements RandomAccess, java.io.Serializable
  9. {
  10. private static final long serialVersionUID = -2764017481108945198L;
  11. private final E[] a;
  12. ArrayList(E[] array) {
  13. a = Objects.requireNonNull(array);
  14. }

Arrays.asList 方法会创建一个 ArrayList,注意 这个 ArrayList 是 Arrays 的内部类 ,不是 java.util 下的ArrayList.它继承了AbstractList 但是没有重写 AbstractList 的 add 方法.

而 AbstractList 的 add 方法是默认直接抛出 UnsupportedOperationException 的。

  1. public boolean add(E e) {
  2. add(size(), e);
  3. return true;
  4. }
  5. public void add(int index, E element) {
  6. throw new UnsupportedOperationException();
  7. }

解决办法

  1. String [] arr= new String[]{"张三","李四"};
  2. List<String> myList= new ArrayList<String>(Arrays.asList(arr));
  3. myList.add("王五");

三、常用的方法

1.Collection

  1. public class CollectionTest01 {
  2. public static void main(String[] args) {
  3. Collection c =new ArrayList();
  4. //向集合中添加元素
  5. c.add(1200);//自动装箱(java5的新特性。),实际上是放进去了一个对象的内存地址。Integer x = new Integer(1200);c.add(new Object());
  6. //获取集合中元素的个数
  7. System.out.println("集合中元素个数是:" + c.size();// 2
  8. //判断集合中是否包含1200
  9. boolean flag = c.contains (1200);
  10. System.out.println(flag);// true
  11. //清空是c.clear();
  12. //删除集合中某个元素
  13. // c.remove(1);
  14. //判断集合是否为空
  15. // system.out.println(c.isEmpty()); // false
  16. //转换成数组(了解,使用不多。)
  17. //object[] objs = c.toArray ();
  18. }
  19. }

2.List

  1. public class ListMethod {
  2. @SuppressWarnings("all")
  3. public static void main(String[] args)(
  4. //void add(int index, Object ele)在index位置插入ele元素
  5. //boolean addAll(int index,Collection eles)从index位置开始将eles中所有的元素添加进来。
  6. //Object get(int index)获取指定index位置的元素
  7. //int indexOf(Object obj) 返回obj在集合中首次出现的位置 lastIndex时末次
  8. //Object remove(int index)移除指定index位置的元素,并返回此元素
  9. //Object set(int index,0bjext ele)设置指定index位置的元素为ele,相当于是替换
  10. //List subList(int fromIndex,int toIndex) 返回从fromIndex到 toIndex位置的子集合。
  11. }
  12. }

3.contains,remove方法分析

深入理解contains方法
contains方法调用了equals方法进行比对。
因为String类重写了equals方法,如果是 User s1 = new User(“abc”),则结果是false。(必须重写equals方法)

  1. import java.util.ArrayList;
  2. import java.util.Collection;
  3. /*
  4. contains方法是用来判断集合中是否包含某个元素的方法。
  5. 那么他在底层中是怎么判断集合中是否包含某个元素的呢?
  6. 调用了equals方法进行比对。
  7. */
  8. public class collectionTest02 {
  9. public static void main(String[] args) {
  10. //创建集合对象
  11. Collection c = new ArrayList();
  12. //向集合中存储元素
  13. String s1 =new String("abc " );
  14. c.add(s1);
  15. String s2 = new String("def ");
  16. c.add(s2);
  17. String x= new String("abc ");
  18. System.out.println(c.contains(x));//true
  19. }
  20. }

image.png

深入理解remove方法
调用了equals方法

  1. import java.util.ArrayList;
  2. import java.util.Collection;
  3. /*
  4. contains方法是用来判断集合中是否包含某个元素的方法。
  5. 那么他在底层中是怎么判断集合中是否包含某个元素的呢?
  6. 调用了equals方法进行比对。
  7. */
  8. public class collectionTest02 {
  9. public static void main(String[] args) {
  10. //创建集合对象
  11. Collection c = new ArrayList();
  12. //创建字符串对象
  13. String s1 = new String("hello");
  14. //加进去
  15. c.add(s1);
  16. //创建一个新的字符串对象
  17. String s2 = new String("hello");
  18. //删除s2
  19. c.remove(s2);
  20. //集合元素的个数是?
  21. System.out.println(c.size());//0
  22. }
  23. }