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

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
二、容器中的设计模式
迭代器模式

Collection 继承了 Iterable 接口,其中的 iterator() 方法能够产生一个 Iterator 对象,通过这个对象就可以迭代遍历 Collection 中的元素。
JDK 1.5 引入了增强的for循环,简化了迭代容器时的写法。
for (元素类型 变量名 : 数组或集合) {
System.out.println(变量名);
}
//使用增强for迭代ArrayList<String> list = new ArrayList<String>();list.add(new String("Monday"));list.add(new String("Tuesday"));list.add(new String("Wensday"));for(String weekday : list){//enhanced for statementSystem.out.println(weekday.toUpperCase());}
迭代器iterator
在Map中不能用,在所有Collection以及子类中使用
Collection c = new Arraylist();c.add("abc");c.add(123);c.add(new Object());//第一步:获取集合迭代器对象IteratorIterator it = c.itrator();/*第二部:通过以上获取的迭代器对象开始迭代以下两个方法是迭代器对象Iterator中的方法:boolean hasNext() 如果仍有对象可以迭代则返回 trueObject next() 返回迭代的下一个元素*/while(it.hasNext()){Object obj = it.next();System.out.println(obj);}}}
适配器模式
Arrays.asList()
该方法是将数组转化成List集合的方法。
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()等方法???
这样是不行的
String [] arr= new String[]{"张三","李四"};List<String> list = Arrays.asList(arr);//也可以这样写//List<String> list = Arrays.asList("张三","李四");list.add("王五");
异常如下:
java.lang.UnsupportedOperationExceptionat java.util.AbstractList.add(AbstractList.java:148)at java.util.AbstractList.add(AbstractList.java:108)at com.example.demo.ClassTest.test2(ClassTest.java:49)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
为什么会这样呢,看下源码就很清楚了:
public static <T> List<T> asList(T... a) {return new ArrayList<>(a);}/*** @serial include*/private static class ArrayList<E> extends AbstractList<E>implements RandomAccess, java.io.Serializable{private static final long serialVersionUID = -2764017481108945198L;private final E[] a;ArrayList(E[] array) {a = Objects.requireNonNull(array);}
Arrays.asList 方法会创建一个 ArrayList,注意 这个 ArrayList 是 Arrays 的内部类 ,不是 java.util 下的ArrayList.它继承了AbstractList 但是没有重写 AbstractList 的 add 方法.
而 AbstractList 的 add 方法是默认直接抛出 UnsupportedOperationException 的。
public boolean add(E e) {add(size(), e);return true;}public void add(int index, E element) {throw new UnsupportedOperationException();}
解决办法
String [] arr= new String[]{"张三","李四"};List<String> myList= new ArrayList<String>(Arrays.asList(arr));myList.add("王五");
三、常用的方法
1.Collection
public class CollectionTest01 {public static void main(String[] args) {Collection c =new ArrayList();//向集合中添加元素c.add(1200);//自动装箱(java5的新特性。),实际上是放进去了一个对象的内存地址。Integer x = new Integer(1200);c.add(new Object());//获取集合中元素的个数System.out.println("集合中元素个数是:" + c.size();// 2//判断集合中是否包含1200boolean flag = c.contains (1200);System.out.println(flag);// true//清空是c.clear();//删除集合中某个元素// c.remove(1);//判断集合是否为空// system.out.println(c.isEmpty()); // false//转换成数组(了解,使用不多。)//object[] objs = c.toArray ();}}
2.List
public class ListMethod {@SuppressWarnings("all")public static void main(String[] args)(//void add(int index, Object ele)在index位置插入ele元素//boolean addAll(int index,Collection eles)从index位置开始将eles中所有的元素添加进来。//Object get(int index)获取指定index位置的元素//int indexOf(Object obj) 返回obj在集合中首次出现的位置 lastIndex时末次//Object remove(int index)移除指定index位置的元素,并返回此元素//Object set(int index,0bjext ele)设置指定index位置的元素为ele,相当于是替换//List subList(int fromIndex,int toIndex) 返回从fromIndex到 toIndex位置的子集合。}}
3.contains,remove方法分析
深入理解contains方法
contains方法调用了equals方法进行比对。
因为String类重写了equals方法,如果是 User s1 = new User(“abc”),则结果是false。(必须重写equals方法)
import java.util.ArrayList;import java.util.Collection;/*contains方法是用来判断集合中是否包含某个元素的方法。那么他在底层中是怎么判断集合中是否包含某个元素的呢?调用了equals方法进行比对。*/public class collectionTest02 {public static void main(String[] args) {//创建集合对象Collection c = new ArrayList();//向集合中存储元素String s1 =new String("abc " );c.add(s1);String s2 = new String("def ");c.add(s2);String x= new String("abc ");System.out.println(c.contains(x));//true}}
深入理解remove方法
调用了equals方法
import java.util.ArrayList;import java.util.Collection;/*contains方法是用来判断集合中是否包含某个元素的方法。那么他在底层中是怎么判断集合中是否包含某个元素的呢?调用了equals方法进行比对。*/public class collectionTest02 {public static void main(String[] args) {//创建集合对象Collection c = new ArrayList();//创建字符串对象String s1 = new String("hello");//加进去c.add(s1);//创建一个新的字符串对象String s2 = new String("hello");//删除s2c.remove(s2);//集合元素的个数是?System.out.println(c.size());//0}}


