集合 — 用于存储批量数据的对象,可以将它看作是一个可变长度的数组
Collection ├——-List 接口:元素按进入先后有序保存,可重复 │—————- LinkedList 接口实现类, 链表, 插入删除, 没有同步, 线程不安全 │—————- ArrayList 接口实现类, 数组, 随机访问, 没有同步, 线程不安全 │—————- Vector 接口实现类 数组, 同步, 线程安全 │ ———————- Stack 是Vector类的实现类 │——-Set 接口: 仅接收一次,不可重复,并做内部排序 │—————-HashSet 使用hash表(数组)存储元素 │———————— LinkedHashSet 链表维护元素的插入次序 │ —————-TreeSet 底层实现为二叉树,元素排好序
有序,存储值可重复
List 集合里添加了一些根据索引来操作集合元素的方法
➢void add(int index, Object ele) //在指定位置添加元素
➢boolean addAll(int index, Collection eles) //在index位置添加大量元素
➢Object get(int index) //查询指定位置元素
➢int indexOf(Object obj) //查询指定元素并返回位置,找不到返回-1
➢int lastIndexOf(Object obj) //从后往回查询指定元素并返回位置
➢Object remove(int index) //删除指定位置元素
➢Object set(int index, Object ele) //修改指定位置元素
➢List subList(int fromIndex, int toIndex) //取出指定范围的子集和
采用数组结构存储元素,在查询操作多时采用
ArrayList 是线程不安全的,而 Vector 是线程安全的,即使为保证 List 集合线程安全,也不推荐使用Vector
@Test public void test3(){ List list = new ArrayList(); list.add("AA"); list.add("BB"); list.add("CC"); list.add("CC"); list.add("CC"); list.set(1, "bbbbb"); System.out.println(list); List list1 = list.subList(1, 3); System.out.println(list1); } @Test public void test2(){ List list = new ArrayList(); list.add("AA"); list.add("BB"); list.add("CC"); list.add("BB"); list.add("BB"); list.add("BB"); System.out.println(list.indexOf("BBBBB")); System.out.println(list.lastIndexOf("BB")); System.out.println(list); list.remove(1); System.out.println(list); } @Test public void test1(){ List list = new ArrayList(); list.add("AA"); list.add("BB"); list.add("CC"); list.add(1, "ff"); System.out.println(list); List list2 = Arrays.asList(1,2,3); list.addAll(1, list2); System.out.println(list); Object o = list.get(4); System.out.println(o); }
采用链表结构存储元素,在频繁的插入或删除元素操作时采用
特有方法:
➢ void addFirst(Object obj) //在头部增加元素
➢ void addLast(Object obj) //在尾部增加元素
➢ Object getFirst() //取头元素
➢ Object getLast() //取尾元素
➢ Object removeFirst() //删除并获取头元素
➢ Object removeLast() //删除并获取尾元素
public void test1(){ LinkedList ll = new LinkedList(); ll.add("AA"); ll.addFirst("BB"); ll.addFirst("CC"); ll.addLast("DD"); System.out.println(ll); Object first = ll.getFirst(); System.out.println(first); System.out.println(ll.getLast()); Object o = ll.removeFirst(); System.out.println(o); System.out.println(ll); System.out.println(ll.removeLast()); System.out.println(ll); }
[CC, BB, AA, DD] CC DD CC [BB, AA, DD] DD [BB, AA]
不可重复,内部排序
HashSet 按 Hash 算法来存储集合中的元素,因此具有很好的存取和查找性能。
HashSet 具有以下特点:
不能保证元素的排列顺序
HashSet 不是线程安全的
集合元素可以是 null
判断元素是否存在的依据是,先比较 hashCode(),若 hashCode 不存在,则直接存储
若 hashCode 存在,则再通过 equals() 比较两个对象的内容。
减少散列冲突:在当前hashCode值处新增一个新的链表, 在同一个hashCode值的后面存储存储不同的对象,这样就保证了元素的唯一性
注意:重写 hashCode 与 equals 方法时,二者必须保持一致!即两个对象完全相同时,产生的hashcode一定要一样,equals要为true
存储形式:
HashSet 采用数组+链表形式存储数据,数组的初始值为16,加载因子为0.75,也就是说,当散列表填装到75%就会扩容,扩容为原来长度的两倍
LinkedHashSet: 是 HashSet 的子类,相较于 HashSet 多了链表维护元素的顺序,遍历效率高于 HashSet 增删效率低于 HashSet
TreeSet的主要功能用于排序
两种排序方法:自然排序和定制排序。默认情况下,TreeSet 采用自然排序
public void treeTest() { TreeSet treeSet = new TreeSet(); treeSet.add(43); treeSet.add(54); treeSet.add(32); treeSet.add(78); treeSet.add(21); System.out.println(treeSet); }
[21, 32, 43, 54, 78] //排序
@Data public class Person implements Comparable{ private String name; private Integer age; public Person(String name, int age) { this.name = name; this.age = age; } }
treeSet.add(new Person("jk",23)); treeSet.add(new Person("ek",45)); System.out.println(treeSet); //报错
比较对象时因为不知道要用哪一个比较,所以会报错
解决方法:
1.自然排序
2.比较器排序
自然排序操作:
1.实现 Comparable接口
2.重写Comparable接口中的compareTo方法
@Override public int compareTo(Object o) { if (o instanceof Person) { Person p=(Person) o; int n=0; if (this.getAge().equals(this.getAge()))//引用类型用equals { return this.getName().compareTo(p.getName()); } return this.getAge().compareTo(p.getAge()); //要是age为int,则为return this.getAge()-p.getAge(); } return 0; }
treeSet.add(new Person("jk",23)); treeSet.add(new Person("ek",45)); treeSet.add(new Person("bf",53)); treeSet.add(new Person("gd",23)); treeSet.add(new Person("ek",45)); System.out.println(treeSet);
[Person(name=bf, age=53), Person(name=ek, age=45), Person(name=gd, age=23), Person(name=jk, age=23)]
定制排序
1.声明一个类实现 Comparator 接口
2.实现接口中的抽象方法 compare(Object o1, Object o2)
3.将该实现类的实例作为参数,传递给 TreeSet 的构造器
利用int compare(T o1,T o2)方法,比较o1和o2的大小:如果方法返回正整数,则表 示o1大于o2;如果返回0,表示相等;返回负整数,表示o1小于o2。
public class MyComparator implements Comparator { @Override public int compare(Object o1, Object o2) { if(o1 instanceof Person && o2 instanceof Person){ Person p1 = (Person) o1; Person p2 = (Person) o2; if(p1.getAge().equals(p2.getAge())){ return p1.getName().compareTo(p2.getName()); } return p1.getAge().compareTo(p2.getAge()); } return 0; } }
MyComparator my = new MyComparator(); TreeSet treeSet = new TreeSet(my);
1、增强 for 循环
2、使用 Iterator 迭代器
package java.util; public interface Iterator<E> { boolean hasNext();//判断是否存在下一个对象元素 E next();//获取下一个元素 void remove();//移除元素 }
public void test() { List list = new ArrayList(); list.add("AA"); list.add("BB"); list.add("CC"); Iterator it = list.iterator(); while (it.hasNext()) { System.out.println(it.next()); } }
AA BB CC
注意:在使用Iterator的时候禁止对所遍历的容器进行改变其大小结构的操作。例如: 在使用Iterator进行迭代时,如果对集合进行了add、remove操作就会出现ConcurrentModificationException异常。因为在你迭代之前,迭代器已经被通过list.itertor()创建出来了,如果在迭代的过程中,又对list进行了改变其容器大小的操作,那么Java就会给出异常。因为此时Iterator对象已经无法主动同步list做出的改变,Java会认为你做出这样的操作是线程不安全的
Iterator和ListIterator主要区别:
一、ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后 遍历。但是ListIterator有hasPrevious()和previous()方法,可以实现逆向 (顺序向前)遍历。Iterator就不可以。
二、ListIterator可以定位当前的索引位置,nextIndex()和previousIndex() 可以实现。Iterator 没有此功能。
三、ListIterator有add()方法,可以向List中插入对象,而Iterator不能。
四、都可实现删除对象,但是ListIterator可以实现对象的修改,set()方法可 以实现。Iterator仅能遍历,不能修改。因为ListIterator的这些功能,可以实 现对LinkedList等List数据结构的操作。
//模仿大神画了张图
Map |--HashMap:是 Map 接口的典型实现类 |--LinkedHashMap: |--Hashtable: 是一个古老的实现,是线程安全的,因此效率低。不建议使用 |--Properties:用于操作属性文件 |--TreeMap:
常用方法:
Object get(Object key) : 根据 key 获取对应的 value boolean containsKey(Object key) :判断是否存在某个key boolean containsValue(Object value) :判断是否存在某个value int size() : 获取当前 Map 中有几对 boolean isEmpty() boolean equals(Object obj) :判断两个 Map 是否完全相等 添加、删除操作: Object put(Object key,Object value) :添加 Object remove(Object key) : 根据 key 删除指定的键值对 void putAll(Map t) : 将 t 中所有的键值对添加到当前 Map 中 void clear() :清空 Map 中所有的键值对
Map 的遍历方式:
//方式一 public void test2() { Map m = new HashMap(); m.put("zxy",32); m.put("ldh",54); m.put("clj",21); m.put("zxl",18); Set set = m.keySet(); for (Object o : set) { Object value = m.get(o); System.out.println(value); } } //方式二 Collection values = m.values(); Iterator it = values.iterator(); while (it.hasNext()) { System.out.println(it.next()); } //方式三 Set en = m.entrySet(); for (Object o : en) { Map.Entry entry= (Map.Entry) o; Object key = entry.getKey(); Object value = entry.getValue(); System.out.println(key +"="+value); }
HashMap是 Map 接口使用频率最高的实现类。
允许使用null键和null值,与HashSet一样,不保证映射的顺序。
HashMap 判断两个 key 相等的标准是:两个 key 通过 equals() 方法返回 true,hashCode 值也相等。
HashMap 判断两个 value相等的标准是:两个 value 通过 equals() 方法返回 true
LinkedHashMap 是 HashMap 的子类
与LinkedHashSet类似,LinkedHashMap 可以维护 Map 的迭代顺序:迭代顺序与 Key-Value 对的插入顺序一致
TreeMap 的 Key 的排序:
自然排序:TreeMap 的所有的 Key 必须实现 Comparable 接口,而且所有的 Key 应 该是同一个类的对象,否则将会抛出 ClasssCastException
定制排序:创建 TreeMap 时,传入一个 Comparator 对象,该对象负责对 TreeMap 中的所有 key 进行排序。此时不需要 Map 的 Key 实现 Comparable 接口
TreeMap判断两个key相等的标准:两个key通过compareTo()方法 或者compare()方法返回0。
若使用自定义类作为TreeMap的key,所属类需要重写equals()和 hashCode()方法,且equals()方法返回true时,compareTo()方法 应返回0
注意: HaspSet底层为HaspMap, TreeSet底层为TreeMap,所以TreeMap的实现方法和TreeSet基本一致
Collections 是一个操作 Set、List 和 Map 等集合的工具类
排序操作:(均为static方法) ➢reverse(List):反转 List 中元素的顺序 ➢shuffle(List):对 List 集合元素进行随机排序 ➢sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序 ➢sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序 ➢swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换 查找、替换 ➢Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素 ➢Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素 ➢Object min(Collection) ➢Object min(Collection,Comparator) ➢int frequency(Collection,Object):返回指定集合中指定元素的出现次数 ➢void copy(List dest,List src):将src中的内容复制到dest中 ➢boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换List对象的所有旧值
public void test3(){ List list = new ArrayList(); list.add(11); list.add(22); list.add(33); list.add(44); list.add(55); Collections.reverse(list); System.out.println(list); Collections.shuffle(list); System.out.println(list); Collections.sort(list); System.out.println(list); Collections.swap(list, 1, 3); System.out.println(list); }
[55, 44, 33, 22, 11] [44, 55, 11, 22, 33] [11, 22, 33, 44, 55] [11, 44, 33, 22, 55]
集合是非常重要的一个知识点,这里也只是简单的列举了一些事例而已,还需要后期反复的复习和研磨,加油鸭!!!