Java集合

Java集合概述

Java集合主要包含两大接口,Collection接口和Map接口。其中Collection接口主要包含List接口和Set接口。接下来主要介绍集合中的各个类的特点即使用方法和区别。
List,Set,Map三者之间的区别?
LIst:元素存储有顺序,可重复。
Set:元素存储无序,不可重复。
Map:键值对存储方式(key-value),key是无序的,不可重复的;value是无序,可重复的。每个键最多映射一个值。
集合底层数据结构及特点
List:

  • ArrayList:底层数据结构为数组(Ojbect[]),查询快,增删慢,线程不安全。
  • LinkedList:底层数据再jdk1.7之前为循环链表,之后为双向链表,查询慢,增删快,线程不安全。
  • Vector:底层数据结构为数组,线程安全。

Set:
HashSet:(无序,唯一)底层数据结构为HashMap,采用HashMap方式存储数据。
LinkedHashSet:其内部实现为LInkedHashMap实现,不过与HashSet实现HashMap有点区别。
TreeSet:(有序,唯一)红黑树(自平衡的排序二叉树)。

Map

  • HashMap:在jdk1.7之前为数组+链表,数组为主体,链表插入方式为头插法。在jdk1.8之后,底层数据结构为数组+链表+红黑树,链表的插入方法为尾插法。

  • HashTable:其底层数据结构为数组+链表。数组为主体,链表解决冲突。

  • TreeMap:红黑树(自平衡的排序二叉树)。

  • LinkedHashMap:继承自HashMap,底层数据结构也为数组+链表+红黑树,并在其基础上增加了一条双向链表,可以保证键值对插入的顺序。

  • CurrentHashMap:ConcurrentHashMap是由Segment数组和HashEntry数组组成。 Segment是一种可重入锁。HashEntry是用于存储键值对数据的。一个Segment包含着一个HashEntry数组,HashEntry是链表结构的,每个Segment守护者HashEntry数组里的元素,当HashEntry数组里的数据需要修改时,需要获取对应的Segment。

    集合扩容机制

List:

  • ArrayList:在jdk1.7之前,其扩容机制为饱汉式,在其创建对象的时候就会开辟长度为10的数组。当扩容是会扩大到原来的2倍,即10->15。在jdk1.8之后,其扩容机制为饿汉式,当ArrayList对象需要添加元素,即调用add()方法时才会开辟为10的空间。扩容过程为先创建对象,数组长度为10,当要添加第11个元素的时候,传建一个新的数组长度为15,将原有元素复制到新数组中。
  • LinkedList:底层为双向链表,没有初始化大小,也没有扩容机制。
  • Vector:初始化长度为10,默认扩容到原来的2倍

Set:
HashSet:数组初始长度为16,其扩容因子为0.75,当元素数量大于16*0.75=12时,触发扩容机制,将数组长度扩容到原来的2倍。
LinkedHashSet:链表不存在扩容机制。
TreeSet:红黑树。

Map

  • HashMap:初始化长度数组为16,当数组长度大于16*0.75=12时,触发扩容机制,当数组长度大于64,链表长度大于8时,将链表转化为红黑树。
  • HashTable:旧数组长度乘2+1。
  • TreeMap:红黑树(自平衡的排序二叉树)。
  • LinkedHashMap:继承自HashMap,底层数据结构也为数组+链表+红黑树,并在其基础上增加了一条双向链表,可以保证键值对插入的顺序。

.

面试常见问题

ArrayList和LinkedList区别?
底层数据结构:ArrayList是数组,LinkedList是双向链表。
是否线程安全:ArrayList和LinkedList都是线程不安全的,都是不同步的。
插入删除元素位置是否受影响:ArrayList采用数组存储,所以插入删除的时间复杂度受元素位置影响。LinkedList采用双向链表存储,插入删除的时间复杂度不受元素位置影响。
是否支持随机访问:LinkedList不支持高效的随机访问,ArrayList支持快速随机访问。快速随机访问是通过元素的序列号快速获取元素对象。
内存空间占用:ArrayList的空间浪费会体现在list结尾会预留一定空间,而linkedList则体现在每一个元素都需要比ArrayList更多的空间。

comparable和comparator区别?
comparable接口下面有个方法是compareTo()方法来进行排序。(java.lang 包)
comparator接口下面是compare()方法来排序。(java.util 包)
当我们需要对集合进行自定义排序时,需要对compareTo()和compare()方法进行重写。我们也可以使用compareTo自制的两个方法。

关于Arrays.asList()方法需要避免的坑。
首先asList()方法是将数组转化为集合,传入的参数为对象数组,而不能是基本数据类型。
当我们使用asList()方法是如果传入参数为基本数据类型则会抛出异常,这时asList方法为Array类里的而不是ArrayList类里的,这里没有重写add(),remove(),clear()。会抛出UnsupportedOperationException异常。
Arrays.asList() ⽅法返回的并不是 java.util.ArrayList ,⽽是 java.util.Arrays 的⼀个内部类,这个内部类并没有实现集合的修改⽅法或者说并没有重写这些⽅法。
我们使用包装类型来演示一遍。

Integer[] myArray = { 1, 2, 3 };
List myList = Arrays.asList(1, 2, 3);
myList.add(4);//运⾏时报错:UnsupportedOperationException
myList.remove(1);//运⾏时报错:UnsupportedOperationException
myList.clear();//运⾏时报错:UnsupportedOperationException

在阿里巴巴开发手册中写道,当时用Arrays.asList()方法时将数组转化为对象不能使用add(),remove(),clear()方法对其元素进行更改。asList()体现的只是适配器模式,其后台数据仍然是数组。

无序性和不可重复性
无序性是指存储在底层数据结构并非按照索引添加,而是根据哈希值添加。
不可重复性是指当添加的元素根据equals()方法判断,并返回false,则会重写equals()和hashCode()方法。

HashSet,LinkedHashSet,TreeSet区别,
HashSet:是Set接口主要实现类,底层是HashMap,线程不安全,可以存储null值。
LinkedHashSet:是HashSet子类,能够按照添加的顺序遍历。
TreeSet:底层是红黑树,能够按照添加元素顺序遍历,排序的方式有自然排序和定制排序。

HashMap和HashTable的区别
线程是否安全:HashMap线程不安全,HashTable线程安全,HashTable内部基本上都被上synchronized修饰过。
效率:HashMap效率高于HashTable。
对于null key和null value的支持:HashMap可以存储null key和null value。但null 作为 键只能有一个,null作为值可以有多个,HashTable不可以有null key 和null value,否则会抛出NullPointerException异常。
初始容量大小和每次扩容机制不同:创建时如果不指定容量,HashTable默认初始大小为11,扩容时扩大到原来的2n+1(2*11+1=23)。HashMap初始默认大小为16,扩容为扩大到原来的2倍。(16,32,64,,128……)。如果创建时给了初始容量,HashTable则会直接使用指定大小,HashMap则会扩容为2的幂次方大小。
HashTable没有扩容。HashMap当链表长度大于8,并且数组长度大于64时,链表会转化为红黑树,以减小搜索时间。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值