ArrayList和linkedList的区别

  1. 底层数据结构:
  • ArrayList:基于动态数组实现,支持快速随机访问。
  • LinkedList:基于双向链表实现,适合频繁的插入和删除操作。
  1. 随机访问性能:
  • ArrayList:由于是基于数组,随机访问速度快,时间复杂度为O(1)。
  • LinkedList:由于是基于链表,随机访问速度慢,时间复杂度为O(n)。
  1. 插入和删除性能:
  • ArrayList:在数组中间插入或删除元素时,需要移动后续所有元素,效率较低,时间复杂度为O(n)。
  • LinkedList:在链表中插入或删除元素时,只需改变节点的指针,效率高,时间复杂度为O(1)。
  1. 内存占用:
  • ArrayList:每个元素只存储数据,内存利用率高。
  • LinkedList:每个元素除了存储数据外,还需要存储两个指针(指向前一个和后一个元素),内存利用率低。
  1. 容量扩展:
  • ArrayList:动态数组,当容量不足时会自动扩展,但扩展操作涉及复制数组,有额外开销。
  • LinkedList:不需要预先分配容量,可以动态地添加节点,没有扩展容量的开销。
  1. 线程安全:
  • 两者都不是线程安全的,但在多线程环境下,LinkedList的插入和删除操作可能更安全,因为它们通常涉及单个节点的修改。
  1. 使用场景:
  • ArrayList:适用于频繁读取元素的场景,如作为缓存。
  • LinkedList:适用于频繁插入和删除元素的场景,如实现队列或栈。
  1. 其他方法:
  • ArrayList:提供toArray方法将列表转换为数组,asList方法将数组转换为固定大小的列表。
  • LinkedList:除了List接口的方法外,还提供了额外的方法,如addFirst、addLast、removeFirst和removeLast等,用于在链表的头部或尾部进行操作。

HashMap和HashTable的区别

  1. 父类不同:
  • HashMap:继承自AbstractMap类。
  • Hashtable:继承自Dictionary类。
  1. 接口方法不同:
  • Hashtable:提供了elements()和contains()方法,这些方法在Dictionary类中定义。
  • HashMap:没有提供这两个方法。
  1. 对null的支持:
  • Hashtable:不允许key和value为null。
  • HashMap:允许key为null(但只能有一个),允许有多个value为null。
  1. 线程安全性:
  • HashMap:非线程安全,适合单线程环境。
  • Hashtable:线程安全,每个方法都加了synchronized关键字,适合多线程环境。
  1. 性能:
  • HashMap:由于非线程安全,通常比Hashtable性能高。
  • Hashtable:由于线程安全,性能可能不如HashMap。
  1. 替代方案:
  • 当需要线程安全时,可以使用ConcurrentHashMap,它比Hashtable性能更好,因为它使用了分段锁。
  1. 初始容量和扩充容量:
  • 两者都可以设置初始容量和负载因子,但具体实现和默认值可能不同。
  1. 计算hash值的方法:
  • 两者可能使用不同的算法来计算hash值,这会影响元素的分布和冲突解决。

Collection 与 Collections 的区别

  1. Collection:
  • 是一个接口,定义了所有单列集合(即不包含重复元素的集合)的基本操作。
  • 子接口包括Set(不允许重复的集合)、List(有序集合,可以重复)。
  • 实现类包括ArrayList、LinkedList、Vector、Stack等。
  1. Collections:
  • 是一个工具类,提供了一系列静态方法来操作或返回各种集合。
  • 提供的方法包括搜索、排序、线程安全化等操作。
  • 不能被实例化,类似于Java中的其他工具类,如Arrays。
  1. 功能区别:
  • Collection定义了集合的基本操作,如添加、删除、遍历等。
  • Collections提供了对集合的辅助操作,如排序(sort)、搜索(binarySearch)、同步(synchronizedCollection)等。
  1. 使用场景:
  • 当你需要创建一个集合并进行基本操作时,你会使用实现Collection接口的类。
  • 当你需要对集合进行更高级的操作,如排序或搜索时,你会使用Collections类提供的方法。

Java的四种引用

  1. 强引用(Strong Reference):
  • 最常见的引用类型。
  • 只要强引用还存在,垃圾回收器永远不会回收被引用的对象。
  • 声明方式:Object obj = new Object();
  1. 软引用(Soft Reference):
  • 内存不足时,垃圾回收器会回收软引用指向的对象。
  • 适用于缓存场景,用于内存敏感的高速缓存。
  • 声明方式:SoftReference softRef = new SoftReference<>(new Object());
  1. 弱引用(Weak Reference):
  • 只要垃圾回收器发现了弱引用对象,就会回收该对象,不管当前内存是否充足。
  • 适用于实现缓存、监听器等,其中对象不再使用时可以被自动回收。
  • 声明方式:WeakReference weakRef = new WeakReference<>(new Object());
  1. 虚引用(Phantom Reference):
  • 虚引用对象在垃圾回收时会被放入引用队列(ReferenceQueue)中,但不会阻止对象的回收。
  • 用于跟踪对象被垃圾回收的活动,进行资源释放等操作。
  • 必须与ReferenceQueue一起使用。
  • 声明方式:PhantomReference phantomRef = new PhantomReference<>(new Object(), new ReferenceQueue<>());
  1. 引用队列(ReferenceQueue):
  • 用于跟踪垃圾回收活动,当引用的对象被回收时,相应的引用会被放入队列中。
  1. 使用场景:
  • 强引用:普通对象的引用。
  • 软引用:内存敏感的高速缓存。
  • 弱引用:缓存、监听器等,对象不再使用时可以被自动回收。
  • 虚引用:对象销毁前的操作,如资源释放。
  1. 回收机制:
  • 强引用:不会被回收。
  • 软引用:内存不足时被回收。
  • 弱引用:一旦发现即被回收。
  • 虚引用:在对象被回收前被放入引用队列。
  1. 注意:
  • 引用类型指的是对象的引用,而不是Reference类的子类(如SoftReference)的引用。

泛型常用特点

  1. 泛型定义:
  • 泛型是Java SE 1.5引入的特性。
  • 允许代码与特定的数据类型无关,从而提高代码的重用性。
  1. 泛型概念:
  • 泛型提供了一种方式,使得类、接口和方法可以在不知道具体类型的情况下编写。
  • 可以在代码执行时指定具体的类型。
  1. 泛型使用示例:
  • 例如,ArrayList是一个泛型类,可以存储任何类型的元素。
  • 通过指定类型参数,如List,可以约束集合中元素的类型。
  1. 使用泛型的好处:
  • 类型安全:编译时检查类型,减少运行时错误。
  • 代码重用:一个类可以处理多种数据类型。
  • 减少类型转换:避免了不必要的类型转换,提高代码的可读性和简洁性。
  • 提高性能:避免了类型擦除带来的性能开销。
  1. 类型擦除:
  • Java泛型在编译时会被擦除,即泛型信息不会保留在字节码中。
  • 这意味着运行时泛型不会增加额外的存储开销。
  1. 泛型与集合:
  • 使用泛型可以定义一个集合来存放不同类型的数据,同时保持类型安全。
  • 例如,可以定义一个List来存储整数,而不需要将所有元素都存储为Object类型。
  1. 泛型约束:
  • 可以通过泛型约束(如extends和super关键字)来限制泛型类型。
  • 例如,List<? extends Number>可以存储任何Number子类型的元素。
  1. 泛型通配符:
  • 通配符(如?)允许在泛型中使用未知的类型。
  • 提供了灵活性,允许在不知道具体类型的情况下操作泛型集合。
10-27 19:13