java集合

110 阅读3分钟

数组与容器(*)

Java 中常用的存储容器就是数组和容器,二者有以下区别:

  • 存储大小是否固定

    • 数组的长度固定
    • 容器的长度可变
  • 数据类型

    • 数组可以存储基本数据类型,也可以存储引用数据类型
    • 容器只能存储引用数据类型,基本数据类型的变量要转换成对应的包装类才能放入容器类中。

排序 (*)

「Arrays中的sort()方法主要是针对各种数据类型(基本数据类型和引用对象类型)的数组元素排序。」

「Collections中的静态方法的Collection.sort()主要是针对集合框架中的动态数组,链表,树,哈希表等( ArrayList、LinkedList、HashSet、LinkedHashSet、HashMap、LinkedHashMap )进行排序。」

但是并不是所有的对象可以进行排序的,要先实现排序还需要定义比较器,也就是定义比较规则 。java提供了两个方法来定义比较规则:

  • 「对象实现Comparable 接口」
  • 「定义比较器实现Comparator接口」

zhuanlan.zhihu.com/p/4147049

Cloneable

Java 中 一个类要实现 clone 功能 必须实现 Cloneable 接口,否则在调用 clone() 时会报 CloneNotSupportedException 异常。

Java 中所有类都默认继承 java.lang.Object 类,在 java.lang.Object 类中有一个方法 clone(),这个方法将返回 Object 对象的一个拷贝。Object 类里的 clone() 方法仅仅用于浅拷贝(拷贝基本成员属性,对于引用类型仅返回指向改地址的引用)。

如果 Java 类需要深拷贝,需要覆写 clone() 方法。

fail-fast

fail-fast 是 Java 容器的一种错误检测机制。当多个线程对容器进行结构上的改变的操作时,就可能触发 fail-fast 机制。

容器在迭代操作中改变元素个数(添加、删除元素)都可能会导致 fail-fast。抛出 ConcurrentModificationException 异常

fail-fast 两种解决方案:

  • 在遍历过程中所有涉及到改变容器个数的地方全部加上 synchronized 或者直接使用 Collections.synchronizedXXX 容器,这样就可以解决。但是不推荐,因为增删造成的同步锁可能会阻塞遍历操作,影响吞吐。
  • 使用并发容器,如:CopyOnWriterArrayList

Java 容器之 List

ArrayList 和 LinkedList

  • ArrayList 基于动态数组实现,存在容量限制,当元素数超过最大容量时,会自动扩容;LinkedList 基于双向链表实现,不存在容量限制。

  • ArrayList 随机访问速度较快,随机插入、删除速度较慢;LinkedList 随机插入、删除速度较快,随机访问速度较慢。

  • ArrayList 和 LinkedList 都不是线程安全的。

Vector 和 Stack

Vector 和 Stack 的设计目标是作为线程安全的 List 实现,替代 ArrayList

  • Vector - Vector 和 ArrayList 类似,也实现了 List 接口。但是, Vector 中的主要方法都是 synchronized 方法,即通过互斥同步方式保证操作的线程安全。
  • Stack - Stack 也是一个同步容器,它的方法也用 synchronized 进行了同步,它实际上是继承于 Vector 类。

ArrayList 默认初始容量大小为 10 ,添加元素时,如果发现容量已满,会自动扩容为原始大小的 1.5 倍。因此,应该尽量在初始化 ArrayList 时,为其指定合适的初始化容量大小,减少扩容操作产生的性能开销。

  • ArrayList 实现了 Cloneable 接口,默认为浅拷贝
  • ArrayList 实现了 Serializable 接口,支持序列化,能通过序列化方式传输。