1java 的容器都有哪些?
Java的容器 list ,map ,set
可以比较的点有 : 有序无序,
可重复不可重复,
键值是否可为null
底层实现的数据结构(数组、链表、哈希。。。)
线程安全性
2.collection 和collections 的区别是什么?
collection是一个jdk 中最根本的接口,定义了集合的基本方法
collections 一个包装类。它包含各种有关集合操作的静态多态方法,不能实例化。像一个collection集合框架中的工具类
3.hashmap 和hashtable 的区别
HashTable和HashMap的区别详解 - 割肉机 - 博客园
hashmap 是基于hash表实现的,每一个元素都是一个key-value 对对内部通过单链表解决冲突问题,容量不足(超过了阀值),同样会自动增长。
hashmap 是非线程安全的,只是用于单线程环境下,多线程环境下采用concurrent 并发包下下的concurrentHashMap.
hashmap 实现了serializable 接口,因此支持序列化,实现了cloneable 接口,能被克隆
【Java集合源码剖析】HashMap源码剖析_兰亭风雨的专栏-CSDN博客_hashmap 源码
hashtable
Hashtable同样是基于哈希表实现的,同样每个元素是一个key-value对,其内部也是通过单链表解决冲突问题,容量不足(超过了阀值)时,同样会自动增长。
Hashtable也是JDK1.0引入的类,是线程安全的,能用于多线程环境中。
Hashtable同样实现了Serializable接口,它支持序列化,实现了Cloneable接口,能被克隆。
【Java集合源码剖析】Hashtable源码剖析_兰亭风雨的专栏-CSDN博客_hashtable源码
(1)两者之间的区别: hashtable 继承自Dictionary hashMap 继承自AbstractMap 类,但两者都实现了map 接口
(2)线程安全性不同,hashtable 是线程安全的,其方法是synchronize的,hashmap 的实现是不同步的,在多线程同事访问一个hash映射事件,而其中至少有一个线程从结构上修改了该映射,则它必须保持外部同步。
(3)是否提供contains 方法
HashMap把Hashtable的contains方法去掉了,改成containsValue和containsKey,因为contains方法容易让人引起误解。
Hashtable则保留了contains,containsValue和containsKey三个方法,其中contains和containsValue功能相同。
(4)key 和value是否允许null值
(5)两个遍历方式的内部实现上不同
Hashtable、HashMap都使用了 Iterator。而由于历史原因,Hashtable还使用了Enumeration的方式 。
(6)hash值不同
哈希值的使用不同,HashTable直接使用对象的hashCode。而HashMap重新计算hash值。
(7)内部实现使用的数组初始化和扩容方式不同
HashTable在不指定容量的情况下的默认容量为11,而HashMap为16,Hashtable不要求底层数组的容量一定要为2的整数次幂,而HashMap则要求一定为2的整数次幂。
Hashtable扩容时,将容量变为原来的2倍加1,而HashMap扩容时,将容量变为原来的2倍。
Hashtable和HashMap它们两个内部实现方式的数组的初始大小和扩容的方式。HashTable中hash数组默认大小是11,增加的方式是 old*2+1。
4、如何决定使用 HashMap 还是 TreeMap?
TreeMap<k,v> 的key值要求实现java.lang.Comparable,所以迭代的时候treemap默认是按照升序来排序的,treemap的实现是基于红黑树结构,适用于按照自然顺序或者自定义顺序遍历键《key》
hashmap<k,v>的key值实现散列hashCode(),分布是散列的、均匀的、不支持排序;数据结构主要是桶(数组),链表或红黑树,适合在map中插入,删除,和定位元素。
因此,如果是想要得到一个有序的结果的时间使用treemap,
如何决定使用 HashMap 还是 TreeMap? - Java知音号 - 博客园
5.说一下 HashMap 的实现原理?
hashmap 使用的是数组加链表来进行实现的,每个数组中都储存着链表
当使用put方法储存key-value 键值对的时间,先使用key 的hashcode方法,得到key经过特定的哈希运算得到的值,然后通过其他运算(?)得到一个值,讲这个值与(length-1)做或操作(&),相当于对数组长度做取余操作,最终得到一个值作为key在数组中的索引值,然后将key-value 键值对储存进去,通过这种方法将储存的不同key-value 键值对“散列”到数组的不同位置
在存储的时间,如果索引位置尚无元素,则直接存储,如果有则调用此key的equals方法和原有的key 进行比较。如果返回true,说明在这个equls 定义的规则上,这两个key值相同,原有的key保留,用新的value 值代替原有的value。如果返回false,那么久说明这两个key在equals 定义的规则下是不同元素,那么就与此链表的下一个节点进行比较,直到最后一个节点都没有相同元素,再下一个是null的时候,就用头插法将此key-value值添加到链表中,
hashmap 对重复元素的处理方式是ke值不变,value覆盖
当使用get方法获取key对应的value时,会和储存key-value时用同样的方法,得到key在数组中的索引值,如果此索引值上没有元素,就返回null。如果此索引值上有元素,那么就拿此key的equals方法与此位置元素上的key进行比较,如果返回true。就返回此位置元素对应的value。如果返回false,就一直按链表往下比较,如果都是返回false,那么就返回null。
6.说一下 HashSet 的实现原理?
hashset 是基于hashmap 实现的,默认构造函数是构建一个初始容量为16,负载因子为0.75的hashmap,封装了一个hashmap来存贮所有的集合,所有放入hashset的集合元素实际上是由hashmap 的key来保存,而hashmap的value则存储一个present,他是一个静态的Objcet对象。
当我们试图将某个类的对象当成hashmap的key,或者试图将这个类的对象放入hashset中保存时,重写该类的equals方法和hashcode方法,而且这两个值必须保持一致:当该类的两个hashcode返回值相同时,他们通过equals()方法比较返回值为true,通常来说,所有参与计算hashcode()返回值得关键属性,都应该用作于equals比较的标准
hashset的其他操作都是基于hahsmap 来实现的
总结一下,hashset 是将hashmap 封装后形成的,在存储方式上与hashmap 不同,hashset 存储相同值的时间会将老的数据覆盖
Java面试题之HashSet 的实现原理?_马小_菜的博客-CSDN博客_说一下hashset的实现原理
7、ArrayList 与LinkList的区别
arrayList 原始长度为8成1.5倍速度增长
1) ArrayList 底层是通过数组来实现的,LinkList 底层是通过双向链表来实现的,
2)ArrayList 在查上的效率更高一些,LinkList 在修改上效率更高,因为Arraylist 在进行增删改的时间要移动数据
底层
用大白话告诉你ArrayList的底层原理 - 我是村村的指挥官 - 博客园
8、如何实现数组和 List 之间的转换?
List转数组:toArray(arrayList.size())方法
数组转List: Arrays 的asList(a) 方法
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);
}
}
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);
}
}
如何实现数组和List之间的转换_yechengchao的博客-CSDN博客_list 转数组
9、ArrayList 和 Vector 的区别是什么?
两者底层都是长度可变的数组存储
区别有以下几点: 1同步性:vector是线程安全的,用synchronized实现线程安全,而ArrayList是线程不安全的,如果只有一个线程会访问集合,那最好使用ArrayList。2、数据容量增长,二者都有一个初始容量大小,采用线性连续存储空间,当存储的元素的个数超过容量是,就需要二者增加存储空间,Vector 增长为原来的一倍,ArrayList 增长为原来的0.5倍
ArrayList和Vector的区别_joli_1034498274的博客-CSDN博客_vector和arraylist的主要区别是
10Array 和ArrayList的区别
1.存储内容上的比较: Array 数组可以存储基本类型和对象类型,ArrayList 却只能包含对象类型;Array 在存储的时间一定是同种类型的元素,ArrayList 却不一定了。
2.空间大小比较 Array 数组的空间大小是固定的,ArrayList是动态数组,前者在事前就需要有合适的空间大小,后者是每次增加新元素的时间都要比较一下空间是否足够
3.方法的比较,ArrayList 方法上比Array更多样化,比如添加addAll()、删除removeAll(),返回迭代Iterator()等。
11.在 Queue 中 poll()和 remove()有什么区别?
poll 若果队列为空的时候,会抛出异常,而 remove() 只会返回null;
12.哪些集合类是线程安全的?
线程安全: 在多线程访问的时间,采用了加锁机制;既当一个线程访问该类的某个数据的时间,会对这个数据进行保护,其他线程不能对其进行访问,直到该线程读取完之后,其他线程才能使用,防止出现数据不一致或者数据被污染的情况
线程不安全:不提供数据访问时的数据保护,多个线程能够同时操作某个数据,从而出现数据不一致或者数据污染的情况。
对于线程不安全问题,一般会使用synchronized 关键字加锁同步控制。
线程安全的集合对象: vector hashTable stringBuffer
非线程安全的集合对象:
- ArrayList :
- LinkedList:
- HashMap:
- HashSet:
- TreeMap:
- TreeSet:
- StringBulider:
13迭代器 Iterator 是什么?
迭代器首先是一种设计模式,用于顺序访问集合对象的元素,无需知道集合对象的底层实现。
Iterator 是可以遍历集合的对象,为各种容器提供了公共的操作接口,隔离对容器的遍历操作和底层实现,从而解耦。
缺点是增加新的集合类需要对应增加新的迭代器类,迭代器类与集合类成对增加
14.Iterator 怎么使用?有什么特点?
Java中的Iterator功能比较简单,并且只能单向移动:
(1) 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。
(2) 使用next()获得序列中的下一个元素。
(3) 使用hasNext()检查序列中是否还有元素。
(4) 使用remove()将迭代器新返回的元素删除。
15Iterator 和 ListIterator 有什么区别?
一.相同点
都是迭代器,当需要对集合中元素进行遍历不需要干涉其遍历过程时,这两种迭代器都可以使用。
二.不同点
1.使用范围不同,Iterator可以应用于所有的集合,Set、List和Map和这些集合的子类型。而ListIterator只能用于List及其子类型。
2.ListIterator有add方法,可以向List中添加对象,而Iterator不能。
3.ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator不可以。
4.ListIterator可以定位当前索引的位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。
5.都可实现删除操作,但是ListIterator可以实现对象的修改,set()方法可以实现。Iterator仅能遍历,不能修改。
Iterator和ListIterator之间有什么区别?_不见风雨怎能见彩虹-CSDN博客_iterator和listiterator区别
16.怎么确保一个集合不能被修改?
我们可以采用Collections包下的unmodifiableMap方法,通过这个方法返回的map,是不可以修改的。他会报 java.lang.UnsupportedOperationException错。
同理:Collections包也提供了对list和set集合的方法。
Collections.unmodifiableList(List)
Collections.unmodifiableSet(Set)