Java集合

一.集合是什么

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

  • 集合类存放的都是对象的引用,而非对象本身,出于表达上的便利,我们称集合中的对象就是指集合中对象的引用(reference)。

  • 集合类型主要有3种:set(集)、list(列表)和map(映射)。

    通俗的说,集合就是放数据对象引用的容器。

二.集合的特点

  • 用于存储对象的容器。
  • 集合的长度是可变的。
  • 集合中不可以存储基本数据类型值。

三.集合和数组的区别

  • 数组的长度是固定的,集合的长度是可变的
  • 数组可以存储基本数据类型和引用数据类型,集合只能存储引用数据类型
  • 数组只能存储同一种类型 ,集合可以存储不同的类型(集合存储的一般也是同一类型)

四.常用集合分类

在这里插入图片描述

1.Collection(单列集合)

Collection集合主要有List和Set两大接口
1.1 List(有序 元素可重复)
  • Vector:底层数据结构是数组,查询快,增删慢,线程同步,线程安全,效率低
  • ArrayList:底层数据结构是数组,查询快,增删慢,线程异步,线程不安全,效率高
  • LinkedList:底层数据结构是链表,查询慢,增删快,线程不安全,效率高
  • 同步:做完一件事再去做下一件事,即排队
    异步:同时做很多事
    多线程:宏观并行,微观串行
1.2 Set(无序 元素不可重复)
  • HashSet 使用hash表(数组)存储元素
  • LinkedHashSet 链表维护元素的插入次序
  • TreeSet 底层实现为二叉树,元素排好序

2.Map(双列集合)

注意了Map是没有继承Collection接口的, Map用于保存具有映射关系的数据,Map集合里保存着两组值,一组用于保存Map的ley,另一组保存着Map的value。

2.1Map接口的常用子类

在这里插入图片描述

  • HashMap: JDK1.8之前HashMap由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的(“拉链法”解决冲突).JDK1.8以后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间,以上是图片描述
  • LinkedHashMap:LinkedHashMap 继承自 HashMap,所以它的底层仍然是基于拉链式散列结构即由数组和链表或红黑树组成,另外LinkedHashMap 在上面结构的基础上,增加了一条双向链表,使得上面的结构可以保持键值对的插入顺序。同时通过对链表进行相应的操作,实现了访问顺序相关逻辑。
  • HashTable: 数组+链表组成的,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的
  • TreeMap: 基于红黑树对所以key进行排序(自然排序和定制排序)
2.2 什么是HaspMap和Map?

Map是接口,Java 集合框架中一部分,用于存储键值对,HashMap是用哈希算法实现Map的类。

2.3 HashMap与HashTable有什么区别?

两者都是用key-value方式获取数据。Hashtable是原始集合类之一(也称作遗留类)。HashMap作为新集合框架的一部分在Java2的1.2版本中加入。它们之间有一下区别:
  ● HashMap和Hashtable大致是等同的,除了非同步和空值(HashMap允许null值作为key和value,而Hashtable不可以)。
  ● HashMap没法保证映射的顺序一直不变,但是作为HashMap的子类LinkedHashMap,如果想要预知的顺序迭代(默认按照插入顺序),你可以很轻易的置换为HashMap,如果使用Hashtable就没那么容易了。
  ● HashMap不是同步的,而Hashtable是同步的。
  ● 迭代HashMap采用快速失败机制,而Hashtable不是,所以这是设计的考虑点。

2.4在Hashtable上下文中同步是什么意思?

同步意味着在一个时间点只能有一个线程可以修改哈希表,任何线程在执行hashtable的更新操作前需要获取对象锁,其他线程等待锁的释放。

2.5 怎样使Hashmap同步?

HashMap可以通过Map m = Collections.synchronizedMap(hashMap)来达到同步的效果。

2.6什么时候使用Hashtable,什么时候使用HashMap

基本的不同点是Hashtable同步HashMap不是的,所以无论什么时候有多个线程访问相同实例的可能时,就应该使用Hashtable,反之使用HashMap。非线程安全的数据结构能带来更好的性能。
  如果在将来有一种可能—你需要按顺序获得键值对的方案时,HashMap是一个很好的选择,因为有HashMap的一个子类 LinkedHashMap。所以如果你想可预测的按顺序迭代(默认按插入的顺序),你可以很方便用LinkedHashMap替换HashMap。反观要是使用的Hashtable就没那么简单了。同时如果有多个线程访问HashMap,Collections.synchronizedMap()可以代替,总的来说HashMap更灵活。

五. Iterator(迭代器)

1.什么是Iterator?

Iterator接口提供了很多对集合元素进行迭代的方法。每一个集合类都包含了可以返回迭代器实例的迭代方法。迭代器可以在迭代的过程中删除底层集合的元素。

这个方法在调用时不需要任何参数,它是访问可迭代序列的一种方式,通常其从序列的第一个元素开始访问,直到所有的元素都被访问才结束。

3.Iterator的使用与遍历移除

//迭代器的使用
	List<String> list = new ArrayList<>();
	Iterator<String> it = list. iterator();
	while(it. hasNext()){
  	String obj = it. next();
	  System. out. println(obj);
	}
//遍历移除元素
	Iterator<Integer> it = list.iterator();
	while(it.hasNext()){
	   it.remove();
	}

3. Iterator与ListIterator有什么区别?

1. ListIterator有add()方法,可以向List中添加对象,而Iterator不能
2. ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator就不可以。
3. ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。
4. 都可实现删除对象,但是ListIterator可以实现对象的修改,set()方法可以实现。Iierator仅能遍历,不能修改。

九.Java集合的快速失败机制 “fail-fast”

是java集合的一种错误检测机制,当多个线程对集合进行结构上的改变的操作时,有可能会产生 fail-fast 机制。

例如:假设存在两个线程(线程1、线程2),线程1通过Iterator在遍历集合A中的元素,在某个时候线程2修改了集合A的结构(是结构上面的修改,而不是简单的修改集合元素的内容),那么这个时候程序就会抛出 ConcurrentModificationException 异常,从而产生fail-fast机制。

原因:迭代器在遍历时直接访问集合中的内容,并且在遍历过程中使用一个 modCount 变量。集合在被遍历期间如果内容发生变化,就会改变modCount的值。每当迭代器使用hashNext()/next()遍历下一个元素之前,都会检测modCount变量是否为expectedmodCount值,是的话就返回遍历;否则抛出异常,终止遍历。

解决办法:

  • 在遍历过程中,所有涉及到改变modCount值得地方全部加上synchronized。

  • 使用CopyOnWriteArrayList来替换ArrayList

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值