[java]集合类详细总结

我宁愿写bug⚠️,也不愿什么都不做 ❗️


💚哈喽!大家好!💚

❤️我是 一看就会,一写就废浩浩🔍❤️

💙让我带你编程带你飞,带你飞进垃圾堆!💙

💜 如果对你有所帮助,请给我点个赞👍!💜


键盘敲烂💥,工资过万💰



一、 集合类介绍

1.1 为什么出现集合类

面向对象语言是对事物的体现都是以对象的形式,为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式

1.2 数组和集合的区别

  • 数组和集合类都是容器。
  • 数组声明了它容纳的元素的类型,而集合不声明。
  • 数组长度是固定的;集合长度是可变的。

数组是静态的,一个数组实例具有固定的大小,一旦创建了就无法改变容量了。而集合是可以动态扩展容量,可以根据需要动态改变大小,集合提供更多的成员方法,能满足更多的需求。

  • 数组中可以存储基本数据类型和引用数据类型,集合只能存储对象。

数组的存放的类型只能是一种(基本类型/引用类型),集合存放的类型可以不是一种(不加泛型时添加的类型是Object)。

  • 数组中存储数据类型是单一的,集合中可以存储任意类型的对象。
  • 数组是java语言中内置的数据类型,是线性排列的,执行效率或者类型检查都是最快的。

1.3 集合类图

  • Collection:所有集合类的根接口

  • Map:映射接口,存放键值对

  • Iterator:遍历集合的迭代接口

在这里插入图片描述在这里插入图片描述

二、 Collection接口与Iterator接口

2.1 Collection接口

  • Collection接口位置 java.util.Collection
  • Collection接口有三个子接口。Collection 接口是 List、Set 和 Queue 接口的父接口,通常情况下不被直接使用。
  • List(列表) ,Set(集)、Queue(队列)

List:元素存取是有序的,可存放重复元素。元素都有下标
Set:元素存取是无序的,不可以存放重复元素。元素没有下标,元素不可以重复
Queue:队列,实现了先进先出

2.1.1 Collection接口的常用方法

方法说明
boolean add(Object o)向集合中加入指定对象o,增加成功返回true,失败false
boolean addAll(Collection c)将指定集合c内的所有元素添加到该集合内,增加成功返回true,否则返回false
void clear()删除集合内的所有元素
boolean contains(Object o)判定集合内是否包含指定元素,是返回true
boolean containsAll(Collection c)判定集合内是否包含集合c的所有元素 ,是返回true
boolean isEmpty()判定是否为空集合,是返回true
Iterator iterator()返回一个Iterator对象,可以用来遍历集合中的元素
boolean remove(Object o)从集合中删除指定元素 o,成功则返回true
boolean removeAll(Collection c)删除该集合中包含集合c的所有元素,若删除了1个及以上的元素则返回true
boolean retainAll(Collection c)删除该集合中除集合c中元素以外的元素,若调用该方法的集合元素改变了,则返回true
int size()返回集合中元素的数目
Object[] toArray()返回一个数组,该数组中包括集合中的所有元素

2.2 Iterator接口

2.2.1 Iterator接口的作用

如果要遍历集合中的元素,在学数组时我们常用for循环遍历数组中的元素,在集合中也可使用传统循环方法实现,此外,集合中也可以使用到Iterator对象来遍历集合的数组,此方法更简单。

Iterator通过遍历(迭代访问)集合中的元素来获取或删除某元素,仅用于遍历集合,可以应用于Set、List、Map以及其子类,Iterator对象也被称为迭代器。

ListIterator在Iterator基础上进行了扩展,允许双向遍历列表,而Iterator只能向后迭代,但ListIterator只能用于List及其子类。

2.2.2 Iterator接口的常用方法

方法接口类型说明
boolean hasNext()Iterator还有元素可以迭代返回true
Object next()Iterator返回下一个元素
void remove()Iterator删除当前元素
void add(Object o)ListIterator将指定元素o插入集合,该元素在下一次调用next()方法时被返回
boolean hasNext()ListIterator存在下一个元素时返回true
boolean hasPrevious()ListIterator存在前一个元素时返回true
Object next()ListIterator返回列表中的下一个元素
Object previous()ListIterator返回列表中的前一个元素
int nextIndex()ListIterator返回列表下一个元素的下标,如果不存在下一个元素,则返回列表的大小
int previousIndex()ListIterator返回列表前一个元素的下标,如果不存在前一个元素,则返回 -1
void remove()ListIterator删除当前元素
void set(Object o)ListIterator将o赋值给当前元素,即上一次调用next方法或previous方法后返回的元素

三、 List 集合

3.1 List 接口的特点

  • List集合为单列集合
  • 元素有序(按照元素的插入顺序保存元素),元素可重复
  • 有索引,可通过索引对元素进行操作。

3.1.1 List 实现类的特点

  • ArrayList
    • 底层数据结构是数组,查询快,增删慢。
    • 线程不安全,效率高
    • 初始容量为10,扩容1.5倍
  • LinkedList
    • 底层数据结构是链表,查询慢,增删快。
    • 线程不安全,效率高。
  • Vector
    • 底层数据结构是数组。
    • 线程安全,效率低,现已经被ArrayList替代
    • 初始容量为10,扩容2倍
  • Stack 栈
    • 底层调用Vector类中的方法,数组实现。
    • 先进后出。

3.2 List 接口的常用方法

方法说明
boolean add(int index, Object element)index为对象element要加入的位置,其他对象的索引位置相对后移1位,索引位置从0开始
E remove(int index)移出列表中指定位置元素
E set(int index, E element)用指定元素替换列表中指定位置元素
E get(int index)返回列表中指定位置元素
int indexOf(Object o)返回列表中指定元素位置的索引。存在多个时,返回第一个的索引位置,不存在返回-1
int lastIndexOf(Object o)返回列表中指定元素位置的索引。存在多个时,返回最后一个的索引位置,不存在返回-1
ListIterator<> listIterator()返回此列表元素的列表迭代器(按适当顺序)
ListIterator<> listIterator(int index)返回此列表元素的列表迭代器(按适当顺序),从列表的指定位置开始
List <> subList(int fromIndex, int toIndex)返回一个指定区域的List集合对象,指定区域从索引fromIndex(包括)到索引toIndex(不包括)

从表中可以看出,List接口提供的适合于自身的常用方法均与索引有关,这是因为List集合为列表类型,以线性方式存储对象,可以通过对象的索引操作对象。

List接口的常用实现类有ArrayList和LinkedList,在使用List集合时,通常情况下声明为List类型,实例化时根据实际情况的需要,实例化为ArrayList或LinkedList,例如:

// 利用ArrayList类实例化List集合
List<String> list = new ArrayList<>();
// 利用LinkedList类实例化List集合
List<String> lsit2 = new LinkedList<>();

3.3 ArrayList

3.3.1 ArrayList 常用方法

  • 增:add(o) add(index,o)
  • 删:remove(o) remove(index)
  • 改:set(index,o)
  • 查:
    • 单查:get(index)

    • 查所有:循环遍历
      1.for循环

         for(int i=0;i<list.size();i++){
             get(i);
         }
      

      2.迭代器

         Iterator it = list.iterator();
         while(it.hasNext()){
             Integer a = (Integer)it.next();
         }
      

      3.for增强循环

         for(Integer i:list){
             i
         }	
      

3.4 LinkedList

3.4.1 LinkedList 类的常用方法

方法说明
void addFirst(E e)将指定元素插入此列表的开头
void addLast(E e)将指定元素插入此列表的结尾
E getFirst()返回列表开头的元素
E getLast()返回列表结尾的元素
E removeFirst()移除列表开头的元素
E removeLast()移除列表结尾的元素

3. Stack 栈

  1. new Stack() 初始化
  2. push(o) 添加元素
  3. pop() 移出栈定元素
  4. peek() 查栈顶元素

四、 Set 集合

4.1 Set 接口的特点

  • 单列集合
  • 无序元素不能重复
  • 无索引

4.1.1 Set 实现类的特点

  • HashSet
    • 底层数据结构是哈希表,存取速度快
    • 线程不安全
    • 元素无序,可以为null
  • LinkedHashSet(HashSet的子类)
    • 哈希表和链表实现了Set接口
    • 元素有序(按照元素的插入顺序保存元素)
  • TreeSet
    • 底层数据结构是红黑树,默认整形排序为从小到大
    • 存储的对象此项实现Comparable接口
    • 线程不安全
    • 元素可以为null

4.2 HashSet

4.2.1 HashSet 特点

  • HashSet:无序不重复,无索引
  • 默认不重复的是虚地址,要想内容不重复,就重写hashcode和equals方法。
  • 底层是HashMap实现,HashMap底层是由数组+链表+红黑树实现
  • HashSet堪称查询速度最快的集合,因为其内部是以HashCode来实现的。它内部元素的顺序是由哈希码来决定的,所以它不保证set的迭代顺序;特别是它不保证该顺序恒久不变
  • 无索引,无法使用for循环来遍历,可以使用增强for循环和迭代器来循环
  • 造成存泄露的原因:HashSet的remove方法也依赖于哈希值进行待删除节点定位,如果由于集合元素内容被修改而导致hashCode方法的返回值发生变更,那么,remove方法就无法定位到原来的对象,导致删除不成功,从而导致内存泄露。

4.2.2 判断重复的方法:

HashSet 判断重复元素是根据元素的 hashCode()的值是否相等,如果不相等,则不用再去执行 equals()方法,两个对象不相等。如果 hashCode()的值相等,需要去执行元素的 equal()方法,如果返回 true 代表像个对象相等,否则两个对象不相等。比较的次数是元素的个数-1.。

4.2.3 HashSet 常用方法

  • 增:add(o)

  • 删:remove(o) 删除指定元素 clear() 移除集合中所有的元素

  • 改:先删除,再添加

  • 查:
    1.for增强循环

     for(Integer i:set){
         i
     }
    

    2.迭代器

       Iterator it=set.iterator();
       while(it.hasNext()){
           Integer a=(Integer)it.next();
       }
    

4.3 TreeSet

4.3.1 TreeSet 特点

无序不重复,但是排序。 线程不安全(不同步)。底层基于TreeMap 实现。

4.3.2 排序比较的方法

TreeSet 是处于排序状态的 Set,他的排序是根据元素的内部比较器(元素类本身实现了 Comparable 接口,重写 ComparaTo 方法)或者外部比较器(专门写一个新类,让这个新类实现Comparator 接口,重写 Compare()方法,进行比较。TreeSet 实例使用它的 compareTo(或compare)方法对所有元素进行比较。比较的次数是元素的个数-1。

1.自然排序
    public static void main(String[] args) {
    TreeSet<String> set = new TreeSet<>();
    //增
    set.add("b");
    set.add("a");
    set.add("c");
    set.add("aa");
    set.add("cc");
    set.add("bb");
    //输出
    System.out.println(set);//按照元素的自然排序输出
}
2.自定义类
    1.内部比较器
    1.类实现Comparable接口,重写compareTo()方法
    public class Person implements Comparable<Person> {
        private String name;
        private int age;

        @Override
        public String toString() {
            return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
        }

        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public Person() {
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        @Override
        public int compareTo(Person o) {
            //比较规则:1.name 2:age
            //1.name
            int i = this.name.compareTo(o.name);
            return i==0?this.age-o.age:i;
        }
    }	
2.测试方法
    public static void main(String[] args) {
    //创建TreeSet
    TreeSet<Person> set = new TreeSet<>();
    //创建person对象
    Person person1 = new Person("tom", 29);
    Person person2 = new Person("tom", 28);
    Person person3 = new Person("jim", 38);
    //放入set
    set.add(person1);
    set.add(person2);
    set.add(person3);
    System.out.println(set);
}

2.外部比较器
    1.类不实现Comparable接口
    2.测试类创建TreeSet使用Comparator有参构造方法
    public static void main(String[] args) {
    //创建TreeSet对象,指定外部比较器
    TreeSet<Person> set = new TreeSet<>(new Comparator<Person>() {
        @Override
        public int compare(Person o1, Person o2) {
            int i = o1.getName().compareTo(o2.getName());
            return i==0?o1.getAge()-o2.getAge():i;
        }
    });
    //创建person对象
    Person person1 = new Person("tom", 29);
    Person person2 = new Person("tom", 28);
    Person person3 = new Person("jim", 38);
    //放入set
    set.add(person1);
    set.add(person2);
    set.add(person3);
    System.out.println(set);

}

五、 Map 集合

5.1 Map接口的特点

Map集合用于保存具有映射关系的数据,在Map集合中保存着两组值,一组值是key键,另一组值是value值。key和value之间存在一对一的关系,通过指定的key键就能找到唯一的value值。Map中的key键不允许重复(key键唯一),value值可以重复

5.1.1 Map实现类的特点

  • HashMap

线程不安全,速度快,允许存放null键,null值。

  • LinkedHashMap

继承自HashMap,它主要是用链表实现来扩展HashMap类

  • HashTable

线程安全,速度慢,不允许存放null键,null值,已被HashMap替代。

  • ConcurrentHashMap

线程安全并且高效的HashMap

  • TreeMap

对键进行排序,排序原理与TreeSet相同

5.2 Map 接口常用方法

方法说明
put(K key, V value)put(K key, V value)
void putAll(Map<? extends K, ? extends V> m)向集合中添加指定集合中所有的键——值映射关系
boolean containsKey(Object key)判断此集合中是否包含指定的键映射关系
boolean containsValue(Object value)判断此集合中是否包含指定的值映射关系
V get(Object key)返回指定的键所映射的值,否则返回null
Set keySet()以Set集合的形式返回该集合中的所有键对象
Collection values()以Collection集合的形式返回该集合中的所有值对象
V remove(Object key)删除并返回键对应的值对象
boolean isEmpty()判断集合是否为空
int size()返回集合中键——值映射关系的个数
boolean equals(Object o)比较指定的键——值映射关系是否相等
void clear()清空集合中所有的映射关系

5.3 HashMap

5.2.1 HashMap 特点

  • 底层实现1.7之前:数组+链表 1.8以后:数组+链表+红黑树
  • key不允许重复,如果key的值相同,后添加的数据会覆盖之前的数据
  • HashMap是非线程安全的

5.4 TreeMap

5.4.1 TreeMap 特点

  • TreeMap基于红黑树数据结构的实现
  • 键可以使用Comparable或Comparator接口, 重写compareTo方法来排序。
  • 自定义的类必须实现接口和重写方法,否则抛异
  • Key值不允许重复,如果重复会把原有的value值覆盖。

5.4.2 排序方法

1.基于JDK写好的实现了Comparable接口的实体类对象排序例如String

public static void main(String[] args) {
    //创建TreeMap对象
    TreeMap<String, String> map = new TreeMap<>();
    //增
    map.put("b", "b的value");
    map.put("a", "a的value");
    map.put("cc", "cc的value");
    map.put("c", "c的value");
    System.out.println("map = " + map);
}

2.自定义类是实现Comparable接口的内部比较器

  1. 自定义实现Comparable接口,重写compareTo(Object o){}
   import java.util.TreeMap;
   
   public class TestPerson {
       public static void main(String[] args) {
           //创建TreeMap对象
           TreeMap<Person, String> map = new TreeMap<>();
           //增
           map.put(new Person("王东阳", 20), "小男神");
           map.put(new Person("李浩", 20), "小帅哥");
           map.put(new Person("范菲菲", 19), "小美女");
           //输出
           System.out.println(map);
       }
   }
  1. 外部比较器

    Person不实现Comparable接口,在TreeMap的构造方法实现

   import java.util.Comparator;
   import java.util.TreeMap;
   import java.util.TreeSet;
   
   public class TestPerson {
       public static void main(String[] args) {
           //创建TreeMap对象
           TreeMap<Person, String> map = new TreeMap<>(new Comparator<Person>() {
               @Override
               public int compare(Person o1, Person o2) {
                   int i = o1.getAge() - o2.getAge();
                   return i==0?o1.getName().compareTo(o2.getName()):i;
               }
           });
           //增
           map.put(new Person("王东阳", 20), "小男神");
           map.put(new Person("李浩", 20), "小帅哥");
           map.put(new Person("范菲菲", 19), "小美女");
           //输出
           System.out.println(map);
       }
   }

5.4.23遍历TreeMap集合的方法

  1. TreeSet

    public static void main(String[] args) {
        //创建TreeMap对象
        TreeMap<String, String> map = new TreeMap<>();
        //增
        map.put("b", "b的value");
        map.put("a", "a的value");
        map.put("cc", "cc的value");
        map.put("c", "c的value");
        //1.keySet
        Set<String> keySet = map.keySet();
        for (String key : keySet) {
            System.out.println(key+":"+map.get(key));
        }
        System.out.println("-----------------------");
        //iterator
        Iterator<String> iterator = keySet.iterator();
        while (iterator.hasNext()){
            String key = iterator.next();
            System.out.println(key+":"+map.get(key));
        }
    }
    
  2. EntrySet

    public static void main(String[] args) {
        //创建TreeMap对象
        TreeMap<String, String> map = new TreeMap<>();
        //增
        map.put("b", "b的value");
        map.put("a", "a的value");
        map.put("cc", "cc的value");
        map.put("c", "c的value");
        //2.entrySet
        Set<Map.Entry<String, String>> entrySet = map.entrySet();
        for (Map.Entry<String, String> entry : entrySet) {
            System.out.println(entry.getKey()+":"+entry.getValue());
        }
        System.out.println("-------------------");
        Iterator<Map.Entry<String, String>> iterator = entrySet.iterator();
        while (iterator.hasNext()){
            Map.Entry<String, String> entry = iterator.next();
            System.out.println(entry.getKey()+"="+entry.getValue());
        }
    }
    

5.5 HashTable

5.5.1 HashTable 特点

  • 和Vector类似,Map体系也有一个自JDK1.2之前遗留的集合工具:Hashtable
  • HashTable和HashMap的区别在于:
    • HashTable是线程安全的,而HashMap是非线程安全的
    • HashTable不允许空的键值对,而HashMap可以
    • HashTable与HashMap都实现Map接口,但二个类的继承的父类不是同一个
  • HashTable底层实现:数组+链表+红黑树
  • 常用方法:同HashMap方法

5.6 ConcurrentHashMap

5.6.1 ConcurrentHashMap 特点

  • ConcurrentHashMap是线程安全并且高效的HashMap

  • 常用方法:同HashMap

  • 数据结构:JDK8 数组+链表+红黑树,数据结构可能是链表,也可能是红黑树,红黑树是为了提高查找效率。采用CAS+Synchronized保证线程安全。

六、 总结各集合类之间的对比

ArraylistLinkedListHashSetTreeSetHashMapTreeMap



有序有序无序有序无序有序



集合集合集合集合键值对键值对
线








键值唯一
相同覆盖
键值唯一
相同覆盖






null
key是
value是
key否
value是





数组链表哈希表二叉树哈希表红黑树

查询快,增删慢查询慢,增删快快速查找快速排序插入、删除和定位元素快按自然顺序或自定义顺序遍历快

Map集合是否能存放null值总结

集合类keyvaluesuper说明
HashTable不能为null不能为nullDictionary线程安全
ConcurrentHashMap不能为null不能为nullAbstractMap线程局部安全
TreeMap不能为null可以为nullAbstractMap线程不安全
HashMap可以为null可以为nullAbstractMap线程不安全
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

haohao_不秃头

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值