Java集合(2)

·常用的集合类
1.Collection接口的子接口包括Set接口和List接口
2.Map接口的实现类有HashMap、TreeMap、Hashtable、ConcurrentHashMap和Properties
3.Set接口的实现类有HashSet、TreeSet、LinkedHashSet
4.List接口的实现类有ArrayList、LinkedList、Stack以及Vector

·Collection集合
1.Collection集合的子接口有Set、List、Queue三种子接口,常用为Set和List
·List:有序容器(元素存入集合的顺序和取出的顺序一致),元素可以重复,可以插入多个null元素,元素都有索引,常用的实现类有
ArrayList、LinkedList和Vector
·Set:无序容器(存入和取出顺序有可能不一致),不可以存储重复元素,只允许存入一个null元素,必须保证元素的唯一性。Set接口 常用实现类是HashSet、LinkedHashSet和TreeSet
·Map是一个键值对集合,存储键、值和之间的映射。key无序,唯一;value不要求有序,允许重复,从Map集合中检索元素时,只要给出 键对象,就会返回对应的值对象。Map的常用实现类:HashMap、TreeMap、Hashtable、LinkedHashMap、ConcurrentHashMap

·集合框架底层数据结构
·Collection
1.List
·ArrayList:Object数组
·Vector:Object数组
·LinkedList:双向循环链表
2.Set
·HashSet(无序唯一):基于HashMap实现,底层使用HashMap来保存元素
·LinkedHashSet:继承于HashSet,其内部是LinkedHashMap实现
·TreeSet(有序唯一):红黑树(自平衡的排序二叉树)

·Map
·HashMap:JDK1.8之前HashMap由数组+链表组成,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的(拉链发解决哈希 冲突)。JDK1.8之后在解决哈希冲突时有很大变化,当链表长度大于阀值(8),且数组长度大于64,将链表转化为红黑树, 以减少搜索时间
·LinkedHashMap:LinkedHashMap继承自HashMap,它底层仍然是基于拉链式散列结构即由数组和链表或红黑树组成,另外, LinkedHashMap在上面结构的基础上,增加了一条双向链表,使得上面的结构可以保持键值对的插入顺序。同时通过 对链表进行相应操作,实现访问顺序相关逻辑。
·HashTable:数组+链表形式组成,数组是HashMap主体,链表主要为了解决哈希冲突而存在
·TreeMap:红黑树(自平衡排序二叉树)

·哪些集合类是线程安全的
1.Vector:比ArrayList多了同步化机制(线程安全),效率低,目前已经不建议使用,在web应用中特别是前台页面,往往效率是优先考 虑的。
2.ConcurrentHashMap:高效且线程安全
3.Stack:栈,堆栈类,先进后出,继承于Vector
4.enumeration:枚举,相当于迭代器

·集合的快速失败机制fail-fast
fai1-fast是集合的一种错误检测机制,当多个线程对集合进行结构改变时,有可能会产生fail-fast机制
假设存在两个线程(线程1和线程2),线程1通过Iterator在遍历集合A的元素,在某个时候线程2修改了集合A的结构(是结构上面的修改,而不是简单的修改集合元素的内容),那么程序就会抛出ConcurrentModificationException异常,从而产生fail-fast机制。

·原因:迭代器在遍历时直接访问集合内容,并且在遍历过程中使用一个modCount变量,集合在被遍历期间如果内容发生改变,就会改变modCount的值,每当迭代器使用hasNext()/next()遍历下一个元素之前,都会检测modCount变量是否为expectedmodCount值,是的话就返回遍历,不是就抛出异常,终止遍历。
·解决办法
1.在遍历过程中,所有涉及到改变modCount值的地方全部加上synchronized
2.使用CopyOnWriteArrayList替换ArrayList

·怎样确保一个集合不能被修改
使用Collections.unmodifiableCollection(Collection c)方法来创建一个只读集合,这样改变集合的任何操作都会抛出 Java.lang.UnsupportedOperationException异常
ex:
Listlist =new ArrayList<>();
list.add(“X”);
Collectionclist=Collections.unmodifiableCollection(list);
clist.add(“Y”);//报错
System.out.println(List.size());

·迭代器Iterator是什么
Iterator接口提供便利任何Collection的接口,可以从一个Collection中使用迭代器方法来获取迭代器实例。迭代器取代了Java集合 框架中的Enumeration,迭代器允许调用者在迭代过程中移除元素

Iterator的使用及特点
ex:

List<String>list=new ArrayList<>();
Iterator<String> it=List.iterator();//创建一个list的迭代器
while(it.hasNext()){
	String obj=it.next();//定义obj=迭代器的遍历元素
	S.o.p(obj)
}

特点:
Iterator的特点是只能单向遍历,更加安全,因为它可以确保在当前遍历的集合元素被更改时,会抛出ConcurrentModificationException异常

·如何边遍历边删除Collection中的元素
边遍历边修改Collection的正确方式是使用Iterator.remove()方法
ex:

Iterator<Integer>it=list.iterator();
while(it.hasNext()){
   if(it.next().equals("sss")){
   	list.remove();
   }
}

错误案例:

for(Integer:i list){
	list.remove(i);
}

当使用foreach(for(Integer:i list))语句时,会自动生成一个iterator来遍历list,但同时list正在被iterator.remove()修改,不允许一个线程遍历Collection,另一个线程修改它。

·Iterator和ListIterator的区别
·Iterator可以遍历Set和List集合,而ListIterator只能遍历List。
·Iterator只能单向遍历,而ListIterator可双向遍历(向前向后遍历)。
·ListIterator实现了Iterator接口,然后添加了额外功能,如:添加一个元素、替换一个元素、获取前面或后面元素的索引位置

·遍历List有哪些不同方式,每种方式实现的原理是什么,list遍历的最佳实践是什么
方式:
1.for循环遍历,基于计数器,在集合外部维护一个计数器,然后依次读取每个位置的元素,当读到最后一个元素停止
2.迭代器遍历,Iterator。是面向对象的设计,屏蔽不同数据集合的特点,统一遍历集合的接口,在Collection中支持了Iterator模式
3.foreach遍历,内部采用iterator实现,使用时不需要显示声明iterator或计数器,优点:代码简洁,不易出错,缺点:只能简单地遍历,不能在遍历过程中 操作数据集合,如删除替换

·最佳实践:Java Collections框架中提供了RandomAccess接口,用来标记List实现是否支持Random Access。
·如果一个数据集合实现了该接口,就意味着它支持Random Access,按位读取元素的平均时间复杂度为O(1),如ArrayList
·如果没有实现该接口,表示不支持,如LinkedList
支持Random Access的列表可以用for循环遍历,否则用iterator或者foreach遍历

·ArrayList优缺点
优点:
1.ArrayList底层以数组实现,是一种随机访问模式,ArrayList实现了RandomAccess接口,查找非常快
2.ArrayList在顺序添加元素时非常方便,比较适合顺序添加、随机访问。
3.自动扩容
缺点
1.删除元素时,需要做一次元素复制操作,如果要复制的元素很多,那么就会比较耗费性能
2.插入元素时,也要做元素复制操作

·如何实现数组和List之间的转换
1.数组转List:使用Arrays.asList(array)进行转换
2.List转数组:使用List自带的toArray()方法

ex:
//List to array

List<String> list=new ArrayList<String>();
list.add("123");
list.add("456");
list.toArray();
//array to list
String[] array=new String[]{"123","456"};
Arrays.asList(array);

·输出格式
List输出格式 list=[1,2,3,4]
map的输出格式 map={b=2,c=3,a=1}
json输出格式json={b:2,c:3,a:1}
json字符串格式 json=’{b:2,c:3,a:1}’
JsonArray格式 JsonArray=[{b:2,c:3,a:1},{b:2,c:3,a:1}]
数组[1,2,3,4,5]

·ArrayList和LinkedList的区别
1.数据结构实现:ArrayList是动态数组的数据结构实现,而linkedlist是双向链表的数据结构实现
2.随机访问效率:ArrayList比LinkedList在随机访问的时候效率要高,因为LinkedList是线性的数据存储方式,需要移动指针从前往后依次查找
3.增加和删除效率:在非首尾的增加和删除操作,LinkedList要比ArrayList效率高,因为ArrayList增删操作要影响数组内的其他数据下标
4.内存空间占比:LinkedList更占内存,因为LinkedList的节点除了存储数据,还存储引用,一个指向前一个元素,一个指向后一个元素
5.线程安全:ArrayList和LinkedList都是不同步的,不保证线程安全

总结:
需要频繁读取集合中的元素时,推荐使用ArrayList,而在插入和删除操作较多时,推荐使用LinkedList

·双向列表
双向列表是双列表,链表的一种,每个数据节点都有两个指针,分别指向直接后继和直接前驱,所以,从双向列表中的任意一个节点开始,都可以很方便地 访问它的前驱节点和后继节点

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值