Java基础之辅助工具类

138 阅读4分钟

Array 和 ArrayList有何区别?

  • Array 可以存储基本数据类型和对象,ArrayList 只能存储对象
  • Array 是指定固定大小的,而 ArrayList 大小是自动扩展的
  • Array 内置方法没有 ArrayList 多,比如 addAll、removeAll、 iteration 等方法只有 ArrayList 有

对于基本类型数据,集合使用自动装箱来减少编码工作量。但是,当处理固定大小的基本数据类型的时候,这种方式相互的一比较慢。

如何实现 Array 和 List 之间的转换?

  • Array 转 List: Arrays.asList(array);
  • List 转 Array: List 的 toArray() 方法

comparable 和 comparator 的区别?

  • compareable 接口实际上是出自 java.lang 包,它有一个 compareTo(Object obj)方法用来排序
  • comparator 接口实际上是出自 java.util 包,它有一个 compare(Object obj1.Object obj2)方法用来排序

一般我们需要对一个集合使用自定义排序时,我们就要重写 compareTo 方法或 compare 方法,当我们需要对某一个集合实现两种排序方式,比如一个 song 对象中的歌名和歌手分别采用一种排序方法的话,我们可以重写 compareTo 方法和使用自制的 Comparator 方法或者以两个 Comparator 来实现歌名排序和歌星名排序,第二种代表我们只能使用两个参数版的 Collections.sort()。

Collection 和 Collections 有什么区别?

  • java.util.Collection 是一个集合接口(集合类的一个顶级接口)。它提供了对集合对象进行基本操作的通用接口方法。Collection 接口在 Java 类库中有很多具体的实现。Collection 接口的意义是为各种具体的集合提供了大化的统一操作方式,其直接继承接口有 List 和 Set。
  • Collections 则是集合类的一个工具类/帮助类,其中提供了一系列静态方法,用于对集合中元素进行排序、搜索以及线程安全等各种操作。

TreeMap 和 TreeSet 在排序时如何让比较元素?Collections 工具类中的 sort() 方法如何比较元素?

TreeSet 要求存放的对象所属的类必须实现 Comparable 接口,该接口提供了比较元素的 compareTo() 方法,当插入元素时会回调该方法比较元素的大小。

TreeMap 要求存放的键值对映射的键必须实现 Comparable 接口从而根据键值对元素进行排序。

Collections 工具类的 sort 方法有两种重载的行式

第一种要求传入的待排序容器中存放的对象比较实现 Comparable 接口以实现元素的比较。

第二种不强制要求容奇中的元素必须可比较,相当于一个临时定义的排序规则,其实就是通过接口注入比较元素大小的算法,也是对回调模式的应用(Java 中对函数式编程的支持)。

Vector、ArrayList 和 LinkedList 的区别是什么?

  1. Vector、ArrayList 都是以类似数组的形式存储在内存中,LinkedList 则以链表的形式进行存储。
  2. List 中的元素有序、允许有重复的元素,Set 中的元素无序、不允许有重复元素
  3. Vector 线程同步,ArrayList、LinkedList 线程不同步
  4. LinkedList 适合指定位置插入、删除操作和不适合查找;ArrayList、Vector 适合查找,不适合指定位置的插入、删除操作
  5. ArrayList 在元素填满容器时会自动扩充容器大小的 50%,而 Vector 则是 100%,因此 ArrayList 更节省空间。

HashTable、HashMap 和 TreeMap 的区别?

  1. HashTable 线程同步,HashMap 非线程同步
  2. HashTable 不允许<键,值>有抗旨,HashMap 允许<键,值>有空值
  3. HashTable 使用 Enumeration,HashMap 使用 Iterator
  4. HashTable 中 hash数组的默认大小是 11,增加方式的 old * 2 + 1,HashMap 中 hash 数组的默认大小是 16,增长方式一定是 2 的指数倍。
  5. TreeMap 能够把它保存的记录根据键排序,默认是按升序排序。

HashMap 的数据结构

JDK 1.8 之前 List+链表

JDK 1.8 之后 List+链表(当链表长度到 8 时,转化为红黑树)

HashMap 的扩容因子

默认 0.75,也就说会浪费四分之一的空间,达到扩容因子时,会将 List 扩容已被,0.75 是时间与空间一个平衡值。

多线程修改 HashMap

多线程同时写入,同时执行扩容操作,多线程扩容可能死锁、丢数据;可以对 HashMap 加入同步锁 Collections.synchronizedMap(hashMap),但是效率很低,因为该锁是互斥锁,同一时刻只能由一个线程执行读写操作,这时候应该使用 ConcurrentHashMap

注意:在使用 Iterator 遍历的时候,LinkedHashMap 会产生 java.util.ConcurrentModificationException。

扩展 HashMap 增加双向链表的实现,号称是最占内存的数据结构。支持 iterator() 是按 Entry 的插入顺序来排序(但是更新不算,如果设置 accessOrder 属性为 true,则所有读写访问都算)。实现上是在 Entry 上再增加属性 before/after 指针,插入时把自己加到 Header Entry 的前面取。如果所有读写访问都要排序,还要把前后 Entry 的 before/after 凭借起来以在链表中删除掉自己。