- java集合详解
- List 接口
- 1)ArrayList
- 2)linkedList
- set 接口
- 1)HashSet
- 2)TreeSet
- 3)集合的遍历
- 4)ListIterator接口
- Map
- 1)HashMap :
- 2) linkedHashMap
- 3)TreeMap
- Collections
集合 — 用于存储批量数据的对象,可以将它看作是一个可变长度的数组
下面集合例子基本都没有使用泛型,但平时使用的时候记得要加上
Collection ├——-List 接口:元素按进入先后有序保存,可重复 │—————- linkedList 接口实现类, 链表, 插入删除, 没有同步, 线程不安全 │—————- ArrayList 接口实现类, 数组, 随机访问, 没有同步, 线程不安全 │—————- Vector 接口实现类 数组, 同步, 线程安全 │ ———————- Stack 是Vector类的实现类 │——-Set 接口: 仅接收一次,不可重复,并做内部排序 │—————-HashSet 使用hash表(数组)存储元素 │———————— linkedHashSet 链表维护元素的插入次序 │ —————-TreeSet 底层实现为二叉树,元素排好序List 接口
有序,存储值可重复
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) //取出指定范围的子集和
1)ArrayList采用数组结构存储元素,在查询操作多时采用
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);
}
2)linkedList
采用链表结构存储元素,在频繁的插入或删除元素操作时采用
特有方法:
➢ 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]set 接口
不可重复,内部排序
1)HashSetHashSet 按 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
2)TreeSetTreeSet的主要功能用于排序
两种排序方法:自然排序和定制排序。默认情况下,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);3)集合的遍历
1、增强 for 循环
2、使用 Iterator 迭代器
package java.util; public interface Iterator{ 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会认为你做出这样的操作是线程不安全的
4)ListIterator接口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 Map
|--HashMap:是 Map 接口的典型实现类
|--linkedHashMap:
|--Hashtable: 是一个古老的实现,是线程安全的,因此效率低。不建议使用
|--Properties:用于操作属性文件
|--TreeMap:
- Map与Collection并列存在。用于保存具有映射关系的数据:Key-Value
- Map 中的 key 和 value 都可以是任何引用类型的数据
- Map 中的 key 用Set来存放,不允许重复,即同一个 Map 对象所对应 的类,须重写hashCode()和equals()方法。
- 常用String类作为Map的“键”。
- key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到唯 一的、确定的 value
常用方法:
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 的遍历方式:
- 方式一:获取 Map 中所有的 key 组成的 Set 。 keySet()
- 方式二: 获取 Map 中所有的 value 组成的 Collection。 values()
- 方式三: 获取 Map 中所有的 Entry(是 Map 的内部类,一个 Entry 对应着一个 Key 和一个 value)组成的 Set
//方式一
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);
}
1)HashMap :
- JDK8 之前,HashMap 由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的(“拉链法”解决冲突)。
- JDK8 以后,在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8 )时,将链表转化为红黑树,以减少搜索时间。
2) linkedHashMapHashMap是 Map 接口使用频率最高的实现类。
允许使用null键和null值,与HashSet一样,不保证映射的顺序。
HashMap 判断两个 key 相等的标准是:两个 key 通过 equals() 方法返回 true,hashCode 值也相等。
HashMap 判断两个 value相等的标准是:两个 value 通过 equals() 方法返回 true
linkedHashMap 是 HashMap 的子类
与linkedHashSet类似,linkedHashMap 可以维护 Map 的迭代顺序:迭代顺序与 Key-Value 对的插入顺序一致
3)TreeMapTreeMap 的 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基本一致
CollectionsCollections 是一个操作 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]
集合是非常重要的一个知识点,这里也只是简单的列举了一些事例而已,还需要后期反复的复习和研磨,加油鸭!!!



