目录
- 集合
- 1.java 容器都有哪些?
- 2. Collection 和 Collections 有什么区别?
- 3.List、Set、Map 之间的区别是什么?
- 4.HashMap 和 Hashtable 有什么区别?
- 5.如何决定使用 HashMap 还是 TreeMap?
- 6.说一下 HashMap 的实现原理?
- 6.LinkedHashMap(了解)
- 7. 说一下 HashSet 的实现原理?
- 8.treeSet
- 9.HashSet 与treeSet
- 10.hashSet和LinkedHashSet
- 11.properties
- 12.ArrayList 和 LinkedList 的区别是什么?
- 13.如何实现数组和 List 之间的转换?
- 14.ArrayList 和 Vector 的区别是什么?
- 15.Array 和 ArrayList 有何区别?
- 16.在 Queue 中 poll()和 remove()有什么区别?
- 17.如何使用线性安全的list
- 18.迭代器 Iterator 是什么?
- 19.Iterator 怎么使用?有什么特点?
- 20.Iterator 和 ListIterator 有什么区别?
- 21.JAVA中循环删除list元素的方法总结
- 22.如何重写equals和hashcode方法(动手写)
- 23.如何实现list排序
- 26.Comparable接口和Comparator接口的比较
- 27.set、map、list遍历方式
- 28.Enumeration接口和Iterator接口的区别有哪些?
- 29.Properties类对于文件的读取和写入
- 30.什么是泛型
- 31.java的泛型是如何工作的?什么是类型擦除?
- 32.什么是泛型中的限定通配符和非限定通配符?
- 33.自定义一个集合
集合
1.java 容器都有哪些?
常用容器的图录:
2. Collection 和 Collections 有什么区别?
- java.util.Collection
是一个集合接口(集合类的一个顶级接口)。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式,其直接继承接口有List与Set。 - Collections则是集合类的一个工具类/帮助类,其中提供了一系列静态方法,用于对集合中元素进行排序、搜索以及线程安全等各种操作。
3.List、Set、Map 之间的区别是什么?
List代表有序、重复的集合;Set代表无序不可重复的集合;Map代表具有映射关系的集合。
4.HashMap 和 Hashtable 有什么区别?
-
hashMap是线性不安全的,hashTable是线性安全的,hashMap效率要比hashTable高。
-
hashMap允许空键值,而hashTable不允许。
-
hashMap的初始容量是16,hashTable初始容量是11,
相同点:都是Map接口的实现类
5.如何决定使用 HashMap 还是 TreeMap?
对于在Map中插入、删除和定位元素这类操作,HashMap是最好的选择。然而,假如你需要对一个有序的key集合进行遍历,TreeMap是更好的选择。
备注:TreeMap性能通常比HashMap要慢,因为它底层采用红黑树来管理KEY-VALUE对,每个键值对都是一个树的节点。
6.说一下 HashMap 的实现原理?
HashMap概述: HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
HashMap的数据结构: 数组+链表。
当我们往Hashmap中put元素时,首先根据key的hashcode重新计算hash值,根绝hash值得到这个元素在数组中的位置(下标),如果该数组在该位置上已经存放了其他元素,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放入链尾.如果数组中该位置没有元素,就直接将该元素放到数组的该位置上。
需要注意Jdk 1.8中对HashMap的实现做了优化,当链表中的节点数据超过八个之后,该链表会转为红黑树来提高查询效率,从原来的O(n)到O(logn)
备注:
《HashMap结构及原理》
6.LinkedHashMap(了解)
是HashMap子类,采用双向链表维护键值对的次序,该链表负责维护Map的迭代顺序,迭代顺序与键值对的插入顺序一致。
7. 说一下 HashSet 的实现原理?
- HashSet底层由HashMap实现,hashMap底层是数组+链表的存储结构
- HashSet的值存放于HashMap的key上
- HashMap的value统一为PRESENT,它是一个静态的Object类。
如果试图将某类的对象作为hashMap的key时,必须重写该类的equals和hashCode方法,而且要保证它亮的返回值一致;即hashCode相等的两个对象,他们通过equals比较应该返回true。(原因:因为如果两个对象的equals相当,但是hashcode不等,hashSet会将他们存储在不同的位置,即也会添加成功,这与hashSet定义就有矛盾了,因为它的元素是不能重复的)
注意:hashMap插入重复的key,会被覆盖(可以结合hashMap底层链表结构理解)。
《详解重写equals()方法就必须重写hashCode()方法的原因》
8.treeSet
treeSet底层使用的就是treeMap,treeMap底层是采用红黑树的数据结构, 红黑树本质上是一棵一定程度上相对平衡的二叉搜索树。
默认情况下,treeSet采用自然排序。(treeSet也支持定制排序)
9.HashSet 与treeSet
HashSet 性能比treeSet性能好,特别是最常用的插入、查询等操作。如果需要一个有序的set,就用treeSet。
10.hashSet和LinkedHashSet
LinkedHashSet是hashSet子类,又基于 LinkedHashMap 来实现的,通过hashcode决定元素的位置,通过双向链表维护元素的次序(与插入顺序一致)。
LinkedHashSet在迭代访问Set中的全部元素时,性能比HashSet好,但是插入时性能稍微逊色于HashSet。
11.properties
是hashTable的子类;
相当于key、value都是String类型的map.
12.ArrayList 和 LinkedList 的区别是什么?
最明显的区别是 ArrrayList底层的数据结构是数组,支持随机访问,而 LinkedList 的底层数据结构是双向循环链表,不支持随机访问。
数组:寻址容易,插入删除困难。
链表:寻址困难,插入删除容易。
13.如何实现数组和 List 之间的转换?
List转换成为数组:调用ArrayList的toArray方法。
数组转换成为List:调用Arrays的asList方法。
14.ArrayList 和 Vector 的区别是什么?
ArrayList 是非线性安全的,Vector 是线性安全的,ArrayList 性能比Vector 好。
15.Array 和 ArrayList 有何区别?
Array可以容纳基本类型和对象,而ArrayList只能容纳对象。
Array是指定大小的,而ArrayList大小是固定的。
Array没有提供ArrayList那么多功能,比如addAll、removeAll和iterator等。
16.在 Queue 中 poll()和 remove()有什么区别?
poll() 和 remove() 都是从队列中取出一个元素,但是 poll() 在获取元素失败的时候会返回空,但是 remove() 失败的时候会抛出异常。
17.如何使用线性安全的list
使用collections的线性安全包装
List list = Collections.synchronizedList(new ArrayList());
...
synchronized (list) {
Iterator i = list.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}
当我们对synchronizedList进行遍历的时候一定不要忘了,在外部也加上synchronized(list),以保证线程安全(这个synchronized块是为了保障内部三行代码在多个线程里同时执行的并发问题)。
https://blog.csdn.net/weixin_45240169/article/details/111400516
18.迭代器 Iterator 是什么?
迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。
19.Iterator 怎么使用?有什么特点?
Java中的Iterator功能比较简单,并且只能单向移动:
(1) 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。
(2) 使用next()获得序列中的下一个元素。
(3) 使用hasNext()检查序列中是否还有元素。
(4) 使用remove()将迭代器新返回的元素删除。
Iterator是Java迭代器最简单的实现,为List设计的ListIterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。
20.Iterator 和 ListIterator 有什么区别?
Iterator可用来遍历Set和List集合,但是ListIterator只能用来遍历List。
Iterator对集合只能是前向遍历,ListIterator既可以前向也可以后向。
ListIterator实现了Iterator接口,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引,等等。
扩展:
21.JAVA中循环删除list元素的方法总结
22.如何重写equals和hashcode方法(动手写)
参照<如何正确的重写equals() 和 hashCode()方法>
23.如何实现list排序
执行结果:
可以用lambda表达式写,更简洁
public class OneTest {
public static void main(String args[]){
List<User> list = new ArrayList<>();
list.add(new User(10,"xm"));
list.add(new User(11,"xh"));
// 升序
// Collections.sort(list, (user1,user2)->user1.getAge()-user2.getAge());
// 降序
Collections.sort(list, (user1,user2)->user2.getAge()-user1.getAge());
System.out.print(list);
}
}
使用stream:
public class OneTest {
public static void main(String args[]){
List<User> list = new ArrayList<>();
list.add(new User(10,"xm"));
list.add(new User(11,"xh"));
List<User> ll = list.stream().sorted((user1,user2)->user2.getAge()-user1.getAge())
.collect(Collectors.toList());
System.out.print(ll);
}
}
26.Comparable接口和Comparator接口的比较
参照<Comparable接口和Comparator接口的比较>
- 1、Comparable和Comparator都是用来实现集合中元素的比较、排序的。
- 2、Comparable是在类内部定义的方法实现的排序,位于java.lang下。
- 3、Comparator是在类外部实现的排序,位于java.util下。
- 4、实现Comparable接口需要覆盖compareTo方法,实现Comparator接口需要覆盖compare方法。
27.set、map、list遍历方式
//使用增强for循环遍历集合,由于Set集合没有get()方法,所有无法使用普通for循环遍历
for (Object obj : stuSet) {
StudentDemo sDemo = (StudentDemo)obj;
System.out.println("姓名:"+sDemo.getStuName()+"-学号:"+sDemo.getStuId()+"-成绩:"+sDemo.getStuGrade());
}
System.out.println("******方法二:******");
//使用Iterator迭代器遍历Set集合
Iterator iterator = stuSet.iterator();
while (iterator.hasNext()) {
StudentDemo stuIt = (StudentDemo)iterator.next();
System.out.println("姓名:"+stuIt.getStuName()+"-学号:"+stuIt.getStuId()+"-成绩:"+stuIt.getStuGrade());
}
list参照21
map遍历参照<java中Map遍历的四种方式>
28.Enumeration接口和Iterator接口的区别有哪些?
Enumeration(英[ɪˌnjuːməˈreɪʃn])速度是Iterator的2倍,同时占用更少的内存。但是,Iterator远远比Enumeration安全,因为其他线程不能够修改正在被iterator遍历的集合里面的对象。同时,Iterator允许调用者删除底层集合里面的元素,这对Enumeration来说是不可能的。
29.Properties类对于文件的读取和写入
30.什么是泛型
泛型就是参数化类型,也就是所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
在泛型出现之前,集合中添加对象只能是object类型的,在取出使用时,必须进行强制类型转换,容易引发ClassCastException。泛型提供了编译器的类型安全,确保你只能把正确类型的对象放入集合中。
31.java的泛型是如何工作的?什么是类型擦除?
泛型是通过类型擦除来实现的,编译器在编译时擦除了所有类型相关的信息,所以在运行时不存在任何类型相关的信息。例如List在运行时仅用一个List来表示。这样做的目的是确保能和java5之前的版本开发二进制类库进行兼容。你无法在运行时访问到类型参数,因为编译器已经把泛型类型转换成了原始类型。
32.什么是泛型中的限定通配符和非限定通配符?
限定通配符是对类型进行了限制。有两种限定通配符,一种是<? extends T>,它通过确保类型必须是T的子类来限定类型的上限。另一种是<? super T>,它通过确保类型必须是T的父类来限定类型的下限。泛型类型必须用限定内的类型来进行初始化,否则会导致编译错误。
非限定通配符用<?>来表示,泛型类型可以用任何类型来进行初始化。