set有哪些实现类?
(1)HashSet
HashSet是set接口的实现类,set下面最主要的实现类就是HashSet(也就是用的最多的),此外还有LinkedHashSet和TreeSet。
HashSet是无序的、不可重复的。通过对象的hashCode和equals方法保证对象的唯一性。
HashSet内部的存储结构是哈希表,是线程不安全的。
(2)TreeSet
TreeSet对元素进行排序的方式:
元素自身具备比较功能,需要实现Comparable接口,并覆盖compareTo方法。
元素自身不具备比较功能,需要实现Comparator接口,并覆盖compare方法。
(3)LinkedHashSet
LinkedHashSet是一种有序的Set集合,即其元素的存入和输出的顺序是相同的。
41、说一下 HashSet 的实现原理?
HashSet实际上是一个HashMap实例,数据存储结构都是数组+链表。
HashSet是基于HashMap实现的,HashSet中的元素都存放在HashMap的key上面,而value都是一个统一的对象PRESENT。
private static final Object PRESENT = new Object();
HashSet中add方法调用的是底层HashMap中的put方法,put方法要判断插入值是否存在,而HashSet的add方法,首先判断元素是否存在,如果存在则插入,如果不存在则不插入,这样就保证了HashSet中不存在重复值。
通过对象的hashCode和equals方法保证对象的唯一性。
42、ArrayList 和 LinkedList 的区别是什么?
ArrayList是动态数组的数据结构实现,查找和遍历的效率较高;
LinkedList 是双向链表的数据结构,增加和删除的效率较高;
43、如何实现数组和 List 之间的转换?
String[] arr = {"zs","ls","ww"};
List<String> list = Arrays.asList(arr);
System.out.println(list);
ArrayList<String> list1 = new ArrayList<String>();
list1.add("张三");
list1.add("李四");
list1.add("王五");
String[] arr1 = list1.toArray(new String[list1.size()]);
System.out.println(arr1);
for(int i = 0; i < arr1.length; i++){
System.out.println(arr1[i]);
}
44、在 Queue 中 poll()和 remove()有什么区别?
(1)offer()和add()区别:
增加新项时,如果队列满了,add会抛出异常,offer返回false。
(2)poll()和remove()区别:
poll()和remove()都是从队列中删除第一个元素,remove抛出异常,poll返回null。
(3)peek()和element()区别:
peek()和element()用于查询队列头部元素,为空时element抛出异常,peek返回null。
45、哪些集合类是线程安全的
Vector:就比Arraylist多了个同步化机制(线程安全)。
Stack:栈,也是线程安全的,继承于Vector。
Hashtable:就比Hashmap多了个线程安全。
ConcurrentHashMap:是一种高效但是线程安全的集合。
46、迭代器 Iterator 是什么?
为了方便的处理集合中的元素,Java中出现了一个对象,该对象提供了一些方法专门处理集合中的元素.例如删除和获取集合中的元素.该对象就叫做迭代器(Iterator)。
47、Iterator 怎么使用?有什么特点?
Iterator 接口源码中的方法:
java.lang.Iterable 接口被 java.util.Collection 接口继承,java.util.Collection 接口的 iterator() 方法返回一个 Iterator 对象
next() 方法获得集合中的下一个元素
hasNext() 检查集合中是否还有元素
remove() 方法将迭代器新返回的元素删除
48、Iterator 和 ListIterator 有什么区别?
(1)ListIterator 继承 Iterator
(2)ListIterator 比 Iterator多方法
add(E e) 将指定的元素插入列表,插入位置为迭代器当前位置之前
set(E e) 迭代器返回的最后一个元素替换参数e
hasPrevious() 迭代器当前位置,反向遍历集合是否含有元素
previous() 迭代器当前位置,反向遍历集合,下一个元素
previousIndex() 迭代器当前位置,反向遍历集合,返回下一个元素的下标
nextIndex() 迭代器当前位置,返回下一个元素的下标
(3)使用范围不同,Iterator可以迭代所有集合;ListIterator 只能用于List及其子类
ListIterator 有 add 方法,可以向 List 中添加对象;Iterator 不能
ListIterator 有 hasPrevious() 和 previous() 方法,可以实现逆向遍历;Iterator不可以
ListIterator 有 nextIndex() 和previousIndex() 方法,可定位当前索引的位置;Iterator不可以
ListIterator 有 set()方法,可以实现对 List 的修改;Iterator 仅能遍历,不能修改。
49、怎么确保一个集合不能被修改?
我们很容易想到用final关键字进行修饰,我们都知道
final关键字可以修饰类,方法,成员变量,final修饰的类不能被继承,final修饰的方法不能被重写,final修饰的成员变量必须初始化值,如果这个成员变量是基本数据类型,表示这个变量的值是不可改变的,如果说这个成员变量是引用类型,则表示这个引用的地址值是不能改变的,但是这个引用所指向的对象里面的内容还是可以改变的。
那么,我们怎么确保一个集合不能被修改?首先我们要清楚,集合(map,set,list…)都是引用类型,所以我们如果用final修饰的话,集合里面的内容还是可以修改的。
我们可以做一个实验:
可以看到:我们用final关键字定义了一个map集合,这时候我们往集合里面传值,第一个键值对1,1;我们再修改后,可以把键为1的值改为100,说明我们是可以修改map集合的值的。
那我们应该怎么做才能确保集合不被修改呢?
我们可以采用Collections包下的unmodifiableMap方法,通过这个方法返回的map,是不可以修改的。他会报 java.lang.UnsupportedOperationException错。
同理:Collections包也提供了对list和set集合的方法。
Collections.unmodifiableList(List)
Collections.unmodifiableSet(Set)
50、队列和栈是什么?有什么区别?
(1)队列先进先出,栈先进后出。
(2)遍历数据速度不同。
栈只能从头部取数据 也就最先放入的需要遍历整个栈最后才能取出来,而且在遍历数据的时候还得为数据开辟临时空间,保持数据在遍历前的一致性;
队列则不同,他基于地址指针进行遍历,而且可以从头或尾部开始遍历,但不能同时遍历,无需开辟临时空间,因为在遍历的过程中不影像数据结构,速度要快的多。