Java教程

java集合详解

本文主要是介绍java集合详解,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

java集合详解

简述

  • 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)HashSet

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

2)TreeSet

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);

3)集合的遍历

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会认为你做出这样的操作是线程不安全的

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 )时,将链表转化为红黑树,以减少搜索时间。

HashMap是 Map 接口使用频率最高的实现类。

允许使用null键和null值,与HashSet一样,不保证映射的顺序。

HashMap 判断两个 key 相等的标准是:两个 key 通过 equals() 方法返回 true,hashCode 值也相等。

HashMap 判断两个 value相等的标准是:两个 value 通过 equals() 方法返回 true

2) LinkedHashMap

LinkedHashMap 是 HashMap 的子类

与LinkedHashSet类似,LinkedHashMap 可以维护 Map 的迭代顺序:迭代顺序与 Key-Value 对的插入顺序一致

3)TreeMap

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

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]

集合是非常重要的一个知识点,这里也只是简单的列举了一些事例而已,还需要后期反复的复习和研磨,加油鸭!!!

这篇关于java集合详解的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!