1.Java 容器分为 Collection 和 Map 两大类
Collection
- List(有顺序的collection,并且可以重复)
ArrayList , LinkedList, Vector , Stack
- Set(不包含重复元素的collection)
HashSet,LinkedHashSet,TreeSet
Map(一组键和值映射的组合,键不能重复)
· HashMap, LinkedHashMap, TreeMap, ConcurrentHashMap,Hashtable
2.ArrayList与LinkedList
1) ArrayList是基于动态数组的数据结构,内存存放地址连续,查询效率比较高,但插入和删除效率比较低。
2) LinkedList是基于链表的数据结构,不需开辟连续的内存空间,插入和删除操作效率比较高,但是查询效率比较低。
适用场景:
当需要对数据进行多次访问则选择ArrayList,如果需要对数据进行多次增删改选择LinkedList。
3.ArrayList与Vector
1) vector方法都是同步,线程安全,而ArrayList不是,因此性能比较好。
2) verctor当元素超过初始化的大小时,会自动将容量翻倍,而ArrayList只能50%,更有利于节约空间。
3) vector可设置增长因子。
适用场景:
不考虑线程安全,选择ArrayList;如果当数据量比较大的时候,vector有一定优势。
4.HashSet与TreeSet
1) TreeSet是二叉树的实现,已经自动排序,不允许放null值。
2) HashSet基于哈希表实现,数据是无序的,可放入null值,有仅只有一个。
3) 两者中的值都不能重复。
4) HashSet要求放入的对象必须实现hashCode()方法,相同内容的String对象hashcode是一致的,因此只能放入一次,而同一个类不同对象可以多次放入不同实例。
适用场景:
通常使用HashSet,需要排序时则使用TreeSet。
5.HashMap和TreeMap
1) hashMap是通过hashcode对其内容进行快速查找,而treeMap本身是按照固定的顺序排列。
hashmap中同样值的map,顺序不同,equals时,为false,而treemap是true
6.HashTable和HashMap
1) 同步性:hashtable是线程安全的,而hashmap是线程不安全的。
2) HashMap允许一个空值的key,多个空值的value。
3) hashtable的键值都不允许为空。
7.HashMap与ConcurrentHashMap的区别
1) hashmap不是线程安全
2) concurrentHashMap是线程安全,并且采用分锁技术,将整个Hash桶进行分段segment,也就是说将大的数组分成几个小的片段segment,而每个小的片段segment都有锁的存在,插入时先获取分段segment锁,然后在插入,由于锁的粒度比较细,并发性能更好一些。
3) 相对于HashTable, ConcurrentHashMap只是锁map的分段segment,而HashTable是锁整个map。当数据量大时,HashTable性能急剧下降。
8.Collection 和 Collections 有什么区别?
· Collection 是一个集合接口,它提供了对集合对象进行基本操作的通用接口方法,所有集合都是它的子类,比如 List、Set 等。
· Collections 是一个包装类,包含了很多静态方法,不能被实例化,就像一个工具类,比如提供的排序方法: Collections. sort(list)。
9.说一下 HashMap 的实现原理?
链表+数组
HashMap 基于 Hash 算法实现的,我们通过 put(key,value)存储,get(key)来获取。当传入 key 时,HashMap 会根据 key. hashCode()计算出 hash 值,根据 hash 值将value 保存在 hash桶bucket 里。当计算出的 hash 值相同时,我们称之为 hash 冲突,HashMap 的做法是用链表和红黑树存储相同 hash 值的 value,当 hash 冲突的个数比较少时,使用链表否则使用红黑树。
10.说一下 HashSet 的实现原理?
HashSet 是基于 HashMap 实现的,HashSet 底层使用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,相关 HashSet 的操作,基本上都是直接调用底HashMap 的相关方法来完成,HashSet 不允许重复的值。
11.数组与list转换
1) List list = Arrays.asList(array); 这个并不是很好的答案,因为此时list只是Arrays的一个静态内部类,没有实现add、remove方法。
2) 最好的方法:List list = new ArrayList(Arrays.asList(array));
3) String[] array=list.toArray(new String[list.size()]);
12.Array 和 ArrayList 有何区别?
· Array 可以存储基本数据类型和对象,ArrayList 只能存储对象。
· Array 是指定固定大小的,而 ArrayList 大小是自动扩展的。
· Array 内置方法没有 ArrayList 多,比如 addAll、removeAll、iteration 等方法只有 ArrayList 有。
13.哪些集合类是线程安全的?
Vector、Hashtable、Stack 都是线程安全的,而像 HashMap 则是非线程安全的,不过在 JDK 1.5 之后随着 Java. util. concurrent 并发包的出现,它们也有了自己对应的线程安全类,比如 HashMap 对应的线程安全类就是 ConcurrentHashMap
14.迭代器 Iterator和 ListIterator
1)Iterator 接口提供遍历任何 Collection 的接口。我们可以从一个Collection 中使用迭代器方法来获取迭代器实例。迭代器取代了 Java 集合框架中的 Enumeration,迭代器允许调用者在迭代过程中移除元素。
Iterator 使用代码如下:
List<String> list = new ArrayList<>();
Iterator<String> it = list. iterator();
while(it. hasNext()){
String obj = it. next();
System. out. println(obj);
}
Iterator 的特点是更加安全,因为它可以确保,在当前遍历的集合元素被更改的时候,就会抛出 ConcurrentModificationException 异常。
2)Iterator 和 ListIterator 有什么区别
·Iterator 可以遍历 Set 和 List 集合,而 ListIterator 只能遍历List。
· Iterator 只能单向遍历,而 ListIterator 可以双向遍历(向前/后遍历)。
· ListIterator 从 Iterator 接口继承,然后添加了一些额外的功能,比如添加一个元素、替换一个元素、获取前面或后面元素的索引位置
15.怎么确保一个集合不能被修改?
可以使用 Collections. unmodifiableCollection(Collection c) 方法来创建一个只读集合,这样改变集合的任何操作都会抛出 Java. lang.UnsupportedOperationException 异常。
示例代码如下:
List<String> list = new ArrayList<>();
list. add("x");
Collection<String> clist = Collections. unmodifiableCollection(list);
clist. add("y"); // 运行时此行报错System. out. println(list. size());
16. java中Map遍历的四种方式
在java中所有的map都实现了Map接口,因此所有的Map(如HashMap, TreeMap, LinkedHashMap, Hashtable等)都可以用以下的方式去遍历。
方法一:在for循环中使用entries实现Map的遍历:
/**
* 最常见也是大多数情况下用的最多的,一般在键值对都需要使用
*/
Map <String,String>map = new HashMap<String,String>();
map.put("熊大", "棕色");
map.put("熊二", "黄色");
for(Map.Entry<String, String> entry : map.entrySet()){
String mapKey = entry.getKey();
String mapValue = entry.getValue();
System.out.println(mapKey+":"+mapValue);
}
方法二:在for循环中遍历key或者values,一般适用于只需要map中的key或者value时使用,在性能上比使用entrySet较好;
Map <String,String>map = new HashMap<String,String>();
map.put("熊大", "棕色");
map.put("熊二", "黄色");
//key
for(String key : map.keySet()){
System.out.println(key);
}
//value
for(String value : map.values()){
System.out.println(value);
}
方法三:通过Iterator遍历;
Iterator<Entry<String, String>> entries = map.entrySet().iterator();
while(entries.hasNext()){
Entry<String, String> entry = entries.next();
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key+":"+value);
}
方法四:通过键找值遍历,这种方式的效率比较低,因为本身从键取值是耗时的操作;
for(String key : map.keySet()){
String value = map.get(key);
System.out.println(key+":"+value);
}
来源:CSDN
作者:累了就学蚊子飞
链接:https://blog.csdn.net/qq642999119/article/details/103764244