Java集合容器整理(详解)

集合框架

什么是集合

  1. 集合是一个对象,它可以容纳其他对象的引用。

  1. 集合类存放于java.util包中。

  1. 集合类型主要有3种:Set(集)、List(列表)和Map(映射)。

  1. 集合存放的都是对象的引用,而非对象本身

集合与数组的区别

  1. 数组可以存储基本数据类型和引用数据类型,而集合中只能存储引用数据类型(可以以包装类形式存储基本数据类型)。

  1. 数组的长度是固定的,而集合的长度是可以改变的。

  1. 集合可以储存不同类型的数据(多态),数组只能储存单一类型数据。

集合类主要有哪些

  1. 集合主要分为Map和Collection(Set、List)两大类。

  1. Set接口的实现类有HashSet、LinkedHashSet和TreeSet。

  1. List接口的实现类有ArrayList、LinkedList和Vector。

  1. Map接口的实现类有HashMap、LinkedHashMap、TreeMap和Hashtable。

Set

Set接口的实现类中的元素是无序(元素存入集合的顺序和取出的顺序不一致)不可重复,只允许存入一个null元素。但是,并不是所有实现了Set接口的集合类都是无序的。例如,LinkedHashSet保证元素添加的自然顺序,TreeSet保证元素的自然顺序。TreeSet它不保留元素的插入顺序,而是按照元素的自然顺序或者指定的比较器进行排序。

Set 接口的三个实现类:HashSet、TreeSet 和 LinkedHashSet 都是线程不安全的,但是,可以通过使用 Collections.newSetFromMap(new ConcurrentHashMap<>()) 方法来创建一个线程安全的 Set 集合。

Set<String> setFromMap = Collections.newSetFromMap(new ConcurrentHashMap<>());

  • TreeSet

TreeSet是一个有序的集合,元素不可重复。它的作用是提供有序的Set集合。

它是基于TreeMap实现的,添加的数据存入了map的key的位置,而value则固定是PRESENT。TreeSet中的元素是有序且不重复的,因为TreeMap中的key是有序且不重复的。

TreeSet底层是使用红黑树来存储元素。 元素按照它们的自然顺序或者指定的比较器进行排序。

如何使用指定比较器

TreeSet<String> treeSet = new TreeSet<>(new Comparator<String>() {
    @Override
    public int compare(String o1, String o2) {
        return o2.compareTo(o1);
    }
});
treeSet.add("banana");
treeSet.add("apple");
treeSet.add("orange");
System.out.println(treeSet);

  • HashSet

HashSet是一个无序(不记录插入的顺序)的集合,元素不可重复,允许一个null元素。基于HashMap集合实现的,类似于前面TreeSet基于TreeMap实现。底层数据结构是哈希表结构。

  • LinkedHashSet

LinkedHashSet 是 HashSet 的有序版本,它维护了一个双向链表来连接所有元素。当需要维护迭代顺序时,就会使用这个类。它是有序的。底层数据结构是双向链表加哈希表。它继承于HashSet,并且其内部是通过LinkedHashMap 来实现的。一个空的新的对象具有默认初始容量(16)和加载因子(0.75)。

List

List是一个接口,List的实现类是有序(和存入数据顺序相同)的集合,其内元素可以重复。允许存入null元素。还支持定位访问——根据元素在列表中的数字位置(下标)来操作元素。

List 接口的三个实现类: ArrayList 和 LinkedList不是线程安全的,Vector是线程安全的。Java 提供了一些方法来使 List 实现类变得线程安全。例如,可以使用 Collections.synchronizedList 方法来创建一个同步的 List。

List list = Collections.synchronizedList(new ArrayList());

这样,就可以在多线程环境中安全地访问 list 集合了。

  • ArrayList

ArrayList 是一个基于数组实现的 List 接口的实现类。它提供了一种动态数组的数据结构,可以根据需要自动增加容量。

ArrayList 支持快速随机访问,这意味着可以快速访问 ArrayList 中的任意元素。但是,当我们删除元素时,内部数组会遍历并移动内存位,因此操作 ArrayList 需要更多时间。

  • LinkedList

它的底层数据结构是双向数据链表,有序,允许元素重复。LinkedList 可以根据下标访问元素。但是,与 ArrayList 不同,LinkedList 不支持快速随机访问。因此,为了按索引查找元素,我们需要手动遍历列表的一部分。这意味着根据下标访问 LinkedList 中的元素可能比访问 ArrayList 中的元素慢。但正是因为其底层的这种数据结构,使其更适合于对元素增删的使用场景,相较于ArrayList效率更高。

  • Vector

Vector是JDK1.0的古老集合类,它继承自AbstractList,实现了List接口。它的底层是数组结构,元素可重复,有序(存放顺序),支持下标索引访问,允许null元素。当底层数组不够用时,ArrayList会在原来的基础上扩展0.5倍,而Vector会扩展1倍。它是线程安全的,因为它的方法都是同步方法(synchronized)。这意味着在多线程环境下,当一个线程正在执行Vector的某个方法时,其他线程不能同时执行该方法,而必须等待该线程执行完毕后才能继续执行。

map

map是一种键值对(key-value)集合。Map集合中的每一个元素都包含一个键(key)对象和一个值(value)对象Map集合是一个双列集合,一个元素包含两个值,一个key,一个value。Map集合中的元素,key和value的数据类型可以相同,也可以不同。Map集合中的元素,key是不允许重复的,value是可以重复的。Map集合中的元素,key和value是一一对应的。

  • HashMap

存储数据采用的是散列表+链表+红黑树结构,元素的存取顺序不能保证一致。线程不安全。

JDK1.8之前HashMap由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的(“拉链法”解决冲突).JDK1.8以后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间。

  • TreeMap

基于红黑树实现,它能够按照键的自然顺序或者自定义比较器排序。线程不安全。

  • LinkedHashMap

继承自 HashMap,所以它的底层仍然是基于拉链式散列结构即由数组和链表或红黑树组成。另外,LinkedHashMap 在上面结构的基础上,增加了一条双向链表,使得上面的结构可以保持键值对的插入顺序。同时通过对链表进行相应的操作,实现了访问顺序相关逻辑。

  • HashTable

HashMap非常相似,但有一个重大区别就是所有的操作都是通过synchronized锁保护的,只有获得了对应的锁,才能进行操作,它线程安全。而Hashtable则不允许null作为key。

迭代器(Iterator)

迭代器在集合遍历时不依赖索引

Java迭代器(Iterator)是 Java 集合框架中的一种机制,它提供了一种在不暴露集合内部实现的情况下遍历集合元素的方法。Java Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法,可用于迭代 ArrayList 和 HashSet 等集合

  • 构建迭代器对象

  • Iterator<类型> it=list.iterator();

  • 迭代器方法

  • it.hasNext();判断当前位置集合中是否还有元素,如果有则返回true,没有则返回false

  • in.next();返回当前指针所指位置的元素,并让指针向指向后面一位元素

  • it.remove()。用迭代器的删除方法。不能用集合的删除方法。

  • 细节

  • 如果当前没有元素,还要强行获取,则会报NoSuchElementException错误

  • 迭代器遍历完成后,指针不会复位

  • 在每一次循环过程中确保使用一次next()方法, eg:调用多次,迭代器会跳过一些元素,导致遍历不完整。

  • 在迭代器遍历时,不能用集合方法进行增加或删除 eg:用来两个变量来分别记录被修改的次数和期望被修改的次数,当调用迭代器的方法时,两个值会同时改变,而调用集合方法时只会改变修改次数。

  • 列表迭代器(ListIterator)比起普通迭代器多了个添加方法,可以在遍历过程中添加元素

public class ListIteratorExample {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<String>();
        list.add("A");
        list.add("B");
        list.add("C");

        ListIterator<String> iterator = list.listIterator();
        while (iterator.hasNext()) {
            String element = iterator.next();
            if (element.equals("B")) {
                iterator.add("D");
            }
        }
        System.out.println(list);
    }
}
//在这个例子中,我们创建了一个包含三个元素的ArrayList。然后,我们使用ListIterator遍历列表,
//并在元素“B”之后添加一个新元素“D”。最后,我们打印出修改后的列表,它包含四个元素“A”、“B”、“D”和“C”。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

日上三杆快起床

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

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

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

打赏作者

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

抵扣说明:

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

余额充值