1.Java容器都有哪些?
- ArrayList、LinkedList、HashSet、TreeSet、HashMap。
2.Collection和Collections有什么区别
- Collection是集合的根接口,定义集合操作元素的方法。
- Collections是集合的工具类,定义操作元素的静态方法。
3.List、Set、Map之间的区别
- List:有序、可重复。在该接口继承Collection接口的同时,又拓展了一些操作元素的方法,如添加到指定索引、根据索引删除、获取指定索引的元素、截取子集合的方法等。
- Set:无序、不可重复的集合。允许保存null,没有索引。没有自己的构造方法,都是继承于Collection接口在的方法
- Map:Map 集合中存储的是键值对,键(Key)不能重复,键允许出现一个null作为键,值(Value)可以重复。键和值都是引用类型。
4、如何决定使用 HashMap 还是 TreeMap?
- 如果要对保存的元素进行排序、遍历,使用TreeMap集合
- 如果要对元素进行插入、删除和指定查找等操作,使用HashMap集合
5、 说一下 HashMap 的实现原理?
- JDK1.8之后,HashMap采用"数组+链表+红黑树"实现
- 当没有哈希冲突时,元素保存到数组中
- 如果出现哈希冲突,在对应的位置上创建链表,元素保存到链表中
- 如果链表的长度大于8,将链表转换为红黑树
- 数据采用键值对key-value的形式保存,键不能重复,能用null作为键;值没有限制,键和值都是引
- 用类型
- 向HashMap集合中添加元素时,原理同HashSet

6、说一下 HashSet 的实现原理?
采用哈希表实现 ,元素不能重复,无序保存,允许保存一个null ,本质是一个HashMap对象
使用HashSet集合时,通常要重写实体类中的equals和hashcode方法
- 如果两个元素的hashCode相同且equals结果为true,视为同一个对象,不能添加。
- 每次向集合中添加元素时,先判断该元素的hashCode是否存在
- 如果不存在,视为不同对象,直接添加
- 如果存在,再判断equals方法的结果
- 如果false,视为不同对象,可以添加
- 如果true,视为同一对象,不能添加
- 由此可见,不能添加的条件是两个对象的hashCode相同且equals的结果为true。
- 如果每次只判断equals的话,由于equals方法通常重写时会判断很多属性,效率不高。
- 如果每次只判断hashCode的话,效率高,但有可能会有哈希冲突,
- 所以先判断hashCode,再判断equals,技能保证效率,又能保证不添加重复元素。
7、ArrayList 和 LinkedList 的区别是什么?
- 这两个类都是List接口的实现类,保存的元素有序可重复,允许保存null
- ArrayList采用数组实现,随机读取效率高,插入删除效率低,适合用于查询
- LinkedList采用双向链表实现,插入删除时不影响其他元素,效率高,随机读取效率低,适合用于频繁更新集合
8、如何实现数组和 List 之间的转换?
- 数组转换为List,使用 Arrays. asList(array) 进行转换。
- List 转换为数组:使用 List 自带的 toArray() 方法。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
/*
* List转Array
*/
List<String> lst = new ArrayList<>();
lst.add("ab");
//使用toArray之后,转换的是Object数组,方法的返回值为 Object[]
Object[] objects = lst.toArray();
System.out.println(Arrays.toString(objects));
/*
* Array转List
*/
String[] str = {"a", "b", "c"};
List<String> list = Arrays.asList(str);
System.out.println(list.toString());
}
}
9、 Array 和 ArrayList 有何区别?
- 存储类型不同:Array只可存储基本数据类型和对象;ArrayList只能存储对象
- Array长度是固定的,ArrayList是一个可变数组,长度可变
10、哪些集合类是线程安全的?
- Stack、Vextor、Properties、Hashtable
11、 Iterator 怎么使用?
import java.util.ArrayList;
import java.util.Iterator;
public class Main {
public static void main(String[] args) {
ArrayList<String> nameList = new ArrayList();
nameList.add("Tom");
nameList.add("Jerry");
nameList.add("LiHua");
nameList.add("Danny");
System.out.println("使用迭代器遍历");
//迭代器
//Collection类型的集合对象.iterator(),获取迭代器
Iterator<String> iterator = nameList.iterator();
// iterator.hasNext()判断集合中是否还有下一个元素
// iterator.next();获取下一个元素
while (iterator.hasNext()) {
String name = iterator.next();
System.out.println(name);
}
}
}
12、线程和进程的区别?
- 进程是操作系统资源分配的基本单元
- 线程是处理器任务调度和执行的基本单位
13、什么是死锁?
- 两个或者两个以上的线程在执行过程中,由于竞争资源或者由于彼此通信而造成的现象
例:定义两个线程类,线程A先获取资源A后,在获取资源B;线程B先获取资源B后,再获取资源A。如果对资源A和资源B使用了synchronized进行同步,就会在线程A获取资源A的时候,线程B无法获取资源A,相反线程B在获取资源B的时候,线程A无法获取资源B,所以两个线程都不会得到另一个资源。
1.PersonA类
public class PersonA implements Runnable {
//定义两个共享的成员变量,刀、叉
private Object knife;
private Object fork;
public PersonA(Object knife, Object fork) {
this.knife = knife;
this.fork = fork;
}
/*
* 该线程执行run方法时,先获取knife对象,等待3s后获取fork对象
*
* */
@Override
public void run() {
synchronized (knife) {
System.out.println(Thread.currentThread().getName() + "获取了knife,3s后获取fork");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (fork) {
System.out.println(Thread.currentThread().getName() + "获取了fork,可以吃饭了");
}
}
}
}
2.PersonB类
public class PersonB implements Runnable {
//定义两个共享的成员变量,刀、叉
private Object knife;
private Object fork;
public PersonB(Object knife, Object fork) {
this.knife = knife;
this.fork = fork;
}
/*
* 该线程执行run方法时,先获取fork对象,等待3s后获取对象knife
*
* */
@Override
public void run() {
synchronized (fork) {
System.out.println(Thread.currentThread().getName() + "获取了fork,3s后获取knife");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (knife) {
System.out.println(Thread.currentThread().getName() + "获取了knife,可以吃饭了");
}
}
}
}
3.测试类Main类
public class Main {
public static void main(String[] args) throws InterruptedException {
Object knife = new Object();
Object fork = new Object();
new Thread(new PersonB(knife,fork),"B").start();
new Thread(new PersonA(knife,fork),"A").start();
}
}
4.运行结果 ,没有结束运行也没有继续进行。

14、 sleep() 和 wait() 有什么区别?
- 都是使线程暂停执行一段时间的方法
- sleep()是Thread类的方法,wait()是Object类中定义的方法
- sleep()方法可以在任何地方使用
- wait()方法只能在synchronized方法或synchronized块中使用
本文深入解析Java集合框架,包括常用容器如ArrayList、LinkedList的特点及应用场景,HashMap与TreeMap的选择依据,以及HashSet的工作原理等核心概念。
432

被折叠的 条评论
为什么被折叠?



