JAVA容器

二、容器

18.java 容器都有哪些?

JAVA中的容器类主要分为两大类,一类是Map类,一类是Collection类,他们有一个共同的父接口Iterator,它提供基本的遍历,删除元素操作。Iterator还有一个子接口LinkIterator,它提供双向的遍历操作。

Collection是一个独立元素的序列,这些元素都服从一条或多条规则,它有三个子接口List,Set和Queue。其中List必须按照插入的顺序保存元素、Set不能有重复的元素、Queue按照排队规则来确定对象的产生顺序(通常也是和插入顺序相同)

Map是一组成对的值键对对象,允许用键来查找值。它允许我们使用一个对象来查找某个对象,也被称为关联数组,或者叫做字典。它主要包括HashMap类和TreeMap类。Map在实际开发中使用非常广,特别是HashMap,想象一下我们要保存一个对象中某些元素的值,如果我们在创建一个对象显得有点麻烦,这个时候我们就可以用上Map了,HashMap采用是散列函数所以查询的效率是比较高的,如果我们需要一个有序的我们就可以考虑使用TreeMap。

19.Collection 和 Collections 有什么区别?

Collection是单列集合的顶级接口,其派生了两个子接口 Set 和 List。定义的是所有单列集合中共有的功能。

Collections则是集合类的一个工具类/帮助类,其中提供了很多静态方法。用于对集合中元素进行排序、搜索以及线程安全等操作。

总之:Collection是一个接口,而Collections是个类。

20.List、Set、Map 之间的区别是什么?

List:有序集合

Set:不重复集合,LinkedHashSet按照插入排序,SortedSet可排序,HashSet无序

Map:键值对集合

21.HashMap 和 Hashtable 有什么区别?

1、HashMap是继承自AbstractMap类,而HashTable是继承自Dictionary类。不过它们都实现了同时实现了map、Cloneable(可复制)、Serializable(可序列化)这三个接口。

2、Hashtable比HashMap多提供了elments() 和contains() 两个方法。

3、HashMap的key-value支持key-value,null-null,key-null,null-value四种。而Hashtable只支持key-value一种(即

key和value都不为null这种形式)。既然HashMap支持带有null的形式,那么在HashMap中不能由get()方法来判断

HashMap中是否存在某个键, 而应该用containsKey()方法来判断,因为使用get的时候,当返回null时,你无法判断到底

是不存在这个key,还是这个key就是null,还是key存在但value是null。

4、线程安全性不同,HashMap的方法都没有使用synchronized关键字修饰,都是非线程安全的,而Hashtable的方法几乎

都是被synchronized关键字修饰的。但是,当我们需要HashMap是线程安全的时,怎么办呢?我们可以通过Collections.synchronizedMap(hashMap)来进行处理,亦或者我们使用线程安全的ConcurrentHashMap。ConcurrentHashMap虽然也是线程安全的,但是它的效率比Hashtable要高好多倍。因为ConcurrentHashMap使用了分段锁,并不对整个数据进行锁定。

5、初始容量大小和每次扩充容量大小的不同 
Hashtable默认的初始大小为11,之后每次扩充,容量变为原来的2n+1。HashMap默认的初始化大小为16。之后每次扩充,容量变为原来的2倍。

6、计算hash值的方法不同 
为了得到元素的位置,首先需要根据元素的 KEY计算出一个hash值,然后再用这个hash值来计算得到最终的位置。

Hashtable直接使用对象的hashCode。hashCode是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值。然后再使用除留余数发来获得最终的位置。 


Hashtable在计算元素的位置时需要进行一次除法运算,而除法运算是比较耗时的。 
HashMap为了提高计算效率,将哈希表的大小固定为了2的幂,这样在取模预算时,不需要做除法,只需要做位运算。位运算比除法的效率要高很多。

HashMap的效率虽然提高了,但是hash冲突却也增加了。因为它得出的hash值的低位相同的概率比较高,而计算位运算

为了解决这个问题,HashMap重新根据hashcode计算hash值后,又对hash值做了一些运算来打散数据。使得取得的位置更加分散,从而减少了hash冲突。当然了,为了高效,HashMap只做了一些简单的位处理。从而不至于把使用2 的幂次方带来的效率提升给抵消掉。

22.如何决定使用 HashMap 还是 TreeMap?

TreeMap<K,V>的Key值是要求实现java.lang.Comparable,所以迭代的时候TreeMap默认是按照Key值升序排序的;TreeMap的实现是基于红黑树结构。适用于按自然顺序或自定义顺序遍历键(key)。

HashMap<K,V>的Key值实现散列hashCode(),分布是散列的、均匀的,不支持排序;数据结构主要是桶(数组),链表或红黑树。适用于在Map中插入、删除和定位元素。

如果你需要得到一个有序的结果时就应该使用TreeMap(因为HashMap中元素的排列顺序是不固定的)。除此之外,由于HashMap有更好的性能,所以大多不需要排序的时候我们会使用HashMap。

23.说一下 HashMap 的实现原理?

简单来说,HashMap由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的,如果定位到的数组位置不含链表(当前entry的next指向null),那么对于查找,添加等操作很快,仅需一次寻址即可;如果定位到的数组包含链表,对于添加操作,其时间复杂度为O(n),首先遍历链表,存在即覆盖,否则新增;对于查找操作来讲,仍需遍历链表,然后通过key对象的equals方法逐一比对查找。所以,性能考虑,HashMap中的链表出现越少,性能才会越好。

24.说一下 HashSet 的实现原理?

首先,我们需要知道它是Set的一个实现,所以保证了当中没有重复的元素。

一方面Set中最重要的一个操作就是查找。而且通常我们会选择

HashSet来实现,因为它专门对快速查找进行了优化。

HashSet使用的是散列函数,那么它当中的元素也就无序可寻。当中是允许元素为null的。

先对实现原理进行一个总结:

(1)基于HashMap实现的,默认构造函数是构建一个初始容量为16,负载因子为0.75 的HashMap。封装了一个 HashMap 对象来存储所有的集合元素,所有放入 HashSet 中的集合元素实际上由 HashMap 的 key 来保存,而 HashMap 的 value 则存储了一个 PRESENT,它是一个静态的 Object 对象。

(2)当我们试图把某个类的对象当成 HashMap的 key,或试图将这个类的对象放入 HashSet 中保存时,重写该类的equals(Object obj)方法和 hashCode() 方法很重要,而且这两个方法的返回值必须保持一致:当该类的两个的 hashCode() 返回值相同时,它们通过 equals() 方法比较也应该返回 true。通常来说,所有参与计算 hashCode() 返回值的关键属性,都应该用于作为 equals() 比较的标准。

(3)HashSet的其他操作都是基于HashMap的。

25.ArrayList 和 LinkedList 的区别是什么?

数据结构:
ArrayList 是动态数组的数据结构实现,而 LinkedList 是双向链表的数据结构实现。

随机访问方式:
LinkedList 是线性的数据存储方式,需要移动指针从前往后依次查找。
所以 ArrayList 比 LinkedList 在随机访问的时候效率要高,

增加和删除:
ArrayList 增删操作要影响数组内的其他数据的下标。
所以在非首尾的增加和删除操作,LinkedList 要比 ArrayList 效率要高,

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

共性:
ArrayList 与 LinkedList 都是单列集合中 List 接口的实现类,他们都是存取有序,有索引,可重复的。

26.如何实现数组和 List 之间的转换?

数组转 List ,使用 JDK 中 java.util.Arrays 工具类的 asList 方法

public static void testArray2List() {
    String[] strs = new String[] {"aaa", "bbb", "ccc"};
    List<String> list = Arrays.asList(strs);
    for (String s : list) {
        System.out.println(s);
    }
}

List 转数组,使用 List 的toArray方法。无参toArray方法返回Object数组,传入初始化长度的数组对象,返回该对象

public static void testList2Array() {
	List<String> list = Arrays.asList("aaa", "bbb", "ccc");
	String[] array = list.toArray(new String[list.size()]);
	for (String s : array) {
		System.out.println(s);
	}
}

27.ArrayList 和 Vector 的区别是什么?

28.Array 和 ArrayList 有何区别?

Array 是数组;ArrayList 是集合

存储内容比较: Array可以包含基本类型和对象类型,ArrayList只能包含对象类型。
空间大小比较: array 是数组,arraylist 是集合,集合可以根据自身变化扩大,而数组创建后不可以变化。
方法上的比较: ArrayList提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等。
Array类型的变量在声明的同时必须进行实例化(至少得初始化数组的大小),而ArrayList可以只是先声明。
对于基本数据类型,集合(ArrayList)使用自动装箱来减少编码工作量;但是Array相对较慢。

29.在 Queue 中 poll()和 remove()有什么区别?

1、offer()和add()的区别
add()和offer()都是向队列中添加一个元素。但是如果想在一个满的队列中加入一个新元素,调用 add() 方法就会抛出一个 unchecked 异常,而调用 offer() 方法会返回 false。可以据此在程序中进行有效的判断!

2、peek()和element()的区别
peek()和element()都将在不移除的情况下返回队头,但是peek()方法在队列为空时返回null,调用element()方法会抛出NoSuchElementException异常。

3、poll()和remove()的区别
poll()和remove()都将移除并且返回队头,但是在poll()在队列为空时返回null,而remove()会抛出NoSuchElementException异常。

30.哪些集合类是线程安全的?

  • Vector

  • Stack

  • Hashtable

  • java.util.concurrent 包下所有的集合类 ArrayBlockingQueue、ConcurrentHashMap、ConcurrentLinkedQueue、ConcurrentLinkedDeque...

31.迭代器 Iterator 是什么?

迭代器是一个设计模式、是一个对象,他可以遍历并选择序列中的元素,而开发人员不需要了解这个序列的底层原理。迭代器又被称为“轻量级”对象,因为创建他的成本很低。

Collection集合元素的通用获取方式:取元素之前先判断集合中是否有元素,如果有,就取一个出来,继续判断,直到所有元素取完。这种取出方式就叫迭代。
集合把这种取出元素的方式描述在iterator接口中。

iterator
iterator的功能简单,且只能单向性移动
使用方法:
1、要使用iterator方法需要容器先返回一个Iterator。(前提)第一次调用next()方法,他返回序列的第一个元素;
2、在使用next()方法获取序列的下一个元素;
3、使用hasnext()方法检查序列中是否还有元素;
4、使用remove()方法删除迭代器返回的新元素。
(迭代其实可以简单地理解为遍历,是一个标准化遍历各类容器里面的所有对象的方法类。)

拓展
Iterator是Java迭代器最简单的实现,为List设计的ListIterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。

32.Iterator 怎么使用?有什么特点?

首先,为什么需要使用迭代器Iterator,原有的for循环和for each不能满足需求吗?

那是因为Iterator模式是用于遍历集合类的标准访问方法。它可以把访问逻辑从不同类型的集合类中抽象出来,从而避免向客户端暴露集合的内部结构。

33.Iterator 和 ListIterator 有什么区别?

1.相同点

都是迭代器,都可以遍历集合中的元素。

2.区别

1)使用范围不同:Iterator能遍历set、list集合,而ListIterator只能遍历list集合。

2)遍历顺序有区别:ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator就不可以。

3)是否能定位当前索引位置:ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。

4)是否能修改对象:都可实现删除对象,但是ListIterator可以实现对象的修改,set()方法可以实现。Iierator仅能遍历,不能修改。

5)  是否能添加对象:ListIterator有add()方法,可以向List中添加对象,而Iterator不能。

34.怎么确保一个集合不能被修改?

(1)通过 Collections. unmodifiableCollection(Collection c)
(2)通过Arrays.asList创建的集合

Collections.unmodifiableMap(map)

Collections.unmodifiableSet(set)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值