请问如何构建一个高效的集合管理系统?

2026-05-05 18:171阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1743个文字,预计阅读时间需要7分钟。

请问如何构建一个高效的集合管理系统?

集合Vector底层结构和ArrayList的对比:- 底层结构:Vector使用数组实现,ArrayList也使用数组实现。- 版本:Vector是早期JDK版本的一部分,而ArrayList是Java 2中引入的。- 线程安全(同步):Vector是线程安全的,ArrayList不是。如果需要线程安全,可以调用ArrayList的synchronizedList方法或使用Collections.synchronizedList。- 效率:线程安全导致Vector在某些操作上效率低于ArrayList。- 扩容倍数:如果使用有参构造器,ArrayList的扩容倍数是1.5倍;无参构造器则是10倍。- 可变性:ArrayList是可变的数组,可以在运行时添加、删除元素。而Vector在Java 1.2之前不安全,容易导致数据丢失或错误。

请问如何构建一个高效的集合管理系统?

集合 Vector底层结构和ArrayList的比较 底层结构 版本 线程安全(同步)效率 扩容倍数 ArrayList 可变数组 jdk1.2 不安全,效率高 如果有参构造就是1.5倍扩容
如果是无参构造
1.第一次10
2.从第二次开始按1.5倍扩 Vector 可变数组Object[] jdk1.0 安全,效率不高 如果是无参,默认10,满后,就按2倍扩容
如果指定大小,则每次直接按2倍扩 ArrayList和LinkedList的比较 底层结构 增删的效率 改查的效率 ArrayList 可变数组 较低
数组扩容 较高 LinkedList 双向链表 较高
通过链表追加 较低

如何选择:

  1. 如果我们改查的操作多,选择ArrayList
  2. 如果我们增删的操作多,选择LinkedList
  3. 一般来说,再程序中,80%-90%都是查询,因此大部分情况会选择ArrayList
Set集合概述和特点

Set集合特点:

  1. 不包含重复元素的集合
  2. 没有带索引的方法,所以不能使用普通for循环遍历
HashSET底层机制说明
  1. HashSet底层是HashMap,第一次添加时,table数组扩容到16,临界值(threshold)是16*加载因子(loadFator)是0.75 = 12;
  2. 如果table数组使用到了临界值12,就会扩容到16*2 =32,新的临界值就是32*0.75 = 24,依次类推;
  3. 在java8中,如果一条链表的元素个数到达TREEIFY_THRESHOLD(默认是8),并且table大小>=MIN_TREEIFY_CAPACITY(默认是64),就会进行树化(红黑树),否则仍然采用数组扩容机制;

Map接口实现类的特点

注意:这里说的是jdk8

  1. Map用于保存具有映射关系的数据:Key-Value
  2. Map中的key和value可以是任何引用类型的数据,会封装到HashMap$Node对象中
  3. Map中的key不允许重复,原因和HashSet一样,如果有相同的key则新的value替换旧的value
  4. Map中的value可以重复
  5. Map的key可以为null,value也可以为null,注意key为null话只能有一个,value为null可以有多个;
  6. 常用String类作为Map的key
  7. key和value之间存在单向一对一关系,即通过指定的key总能找到对应的value
HashMap介绍
  1. Map接口的常用实现类:HashMap、Hashtable和Properties
  2. HashMap是Map接口使用频率最高的实现类
  3. HashMap是以key-val对应的方式来存储数据
  4. key值不能重复,但是value可以重复,允许使用null键和null值
  5. 如果添加相同的key,则会覆盖原来的key-val,等同于修改(key不会替换,val会替换)
  6. 与HashSet一样,不保证映射的顺序,因为磁层是以hash表的方式来存储的
  7. HashMap没有实现同步,因此是线程不安全的
HashTable介绍
  1. 存放的元素是键值对:k-v
  2. hashTable的键和值都不能为null,否则会抛出NullPointerException
  3. hashTable使用方法基本上和HashMap一样
  4. hashTable是线程安全的,hashMap是线程不安全的
Hashtable和HashMap对比 版本 线程安全(同步) 效率 允许null键null值 HashMap 1.2 不安全 高 可以 Hashtable 1.0 安全 较低 不可以 Properties基本介绍
  1. Properties类继承自Hashtable类并且实现了Map接口,也是使用一种键值对的形式来保存数据。
  2. 它的使用特点和Hashtable类似
  3. Properties还可以用于从xxx.properties文件中,加载数据到Properties类对象,并进行读取和修改
  4. key和value不能为null
开发中如何选择集合实现类

在开发中,选择上面集合实现类,主要取决于业务操作特点,然后根绝结合实现类特性进行选择,分析如下:

1.先判断存储的类型(一组对象[单列]或是一组键值对[双列])

2.一组对象[单列]:Collection接口

​ 允许重复:List

​ 增删多:LinkedList[底层维护了一个双向链表]

​ 改查多:ArrayList[底层维护Object类型的可变数组]

​ 不允许重复:Set

​ 无序:HashSet [底层是HashMap,维护了一个哈希表,即(数组+链表+红黑树)]

​ 排序:TreeSet

​ 插入和取出顺序一致:LinkedHashSet,维护的是数组+双向链表

3.一组键值对[双列]:Map

​ 键无序:HashMap [底层是:哈希表 jdk7:数组+链表,jdk8:数组+链表+红黑树]

​ 键排序:TreeMap

​ 键插入和取出顺序一致:LinkedHashMap

​ 读取文件:Properties

HashSet和TreeSet是如何实现去重的
  • HashSet去重机制:hashCode() + equals(),底层先通过存入对象,进行运算得到hash值,通过hash值得到对应的索引,如果发现得到的索引对应table中相同索引的位置没有数据则直接存放,如果有数据,则会进行equals比较[遍历比较],如果比较后不相同则加入,否则不加入。
  • TreeSet去重机制:如果你传入了一个Comparator匿名对象,就是用实现的compare去重,如果方法返回0,就认为是相同的元素/数据,就不添加,如果你没有传入一个Comparator匿名对象,则以你添加的对象实现的Comparable接口的compareTo去重。
分析下面代码

package com.example.homework; import java.util.HashSet; import java.util.Objects; /** * @Author 郜庆辉 * @Time 2022/5/28 17:47 * @Version 1.0 */ public class Homework4 { public static void main(String[] args) { HashSet set = new HashSet(); Person p1 = new Person(1001, "AA"); Person p2 = new Person(1002, "BB"); set.add(p1); //第一次添加的1001, "AA",p1的hash值为10 set.add(p2); System.out.println(set); p1.name = "CC"; //修改后的1001, "CC",p1的hash值还是10,只不过CC把AA占了 System.out.println(set); set.remove(p1);//remove时也会计算hash值,但是计算的是1001, "CC"的hash值;hash值为11,删除的就hash值为11的索引位置;即p1没有删除成功,因为p1的hash为10; System.out.println(set); set.add(new Person(1001, "CC"));//这里添加的是按照1001, "CC"hash值进行添加的,同样会添加成功,hash值为12; System.out.println(set); set.add(new Person(1001,"AA")); //这里又添加的1001,"AA"hash值为10,跟p1的hash值一样,按理说不会添加成功,但是现在P1是1001,"CC",hash不一样时用equals比较,value不同,也可以添加成功。 System.out.println(set); } } class Person { public int id; public String name; public Person(int id, String name) { this.id = id; this.name = name; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return id == person.id && Objects.equals(name, person.name); } @Override public int hashCode() { return Objects.hash(id, name); } // @Override // public String toString() { // return "Person{" + // "id=" + id + // ", name='" + name + '\'' + // '}'; // } } Vector和ArrayList比较 底层结构 版本 线程安全(同步)效率 扩容倍数 ArrayList 可变数组 jdk1.2 不安全,效率高 如果使用有参构造器按照1.5倍扩容,如果使用无参构造器:
1.第一次扩容10
2.从第二次开始按照1.5倍扩容 Vector 可变数组
Object[] jdk1.0 安全,效率不高 如果是无参,默认10,满后按照2倍扩容
如果是指定大小创建Vector,则每次按照2倍扩容。

本文共计1743个文字,预计阅读时间需要7分钟。

请问如何构建一个高效的集合管理系统?

集合Vector底层结构和ArrayList的对比:- 底层结构:Vector使用数组实现,ArrayList也使用数组实现。- 版本:Vector是早期JDK版本的一部分,而ArrayList是Java 2中引入的。- 线程安全(同步):Vector是线程安全的,ArrayList不是。如果需要线程安全,可以调用ArrayList的synchronizedList方法或使用Collections.synchronizedList。- 效率:线程安全导致Vector在某些操作上效率低于ArrayList。- 扩容倍数:如果使用有参构造器,ArrayList的扩容倍数是1.5倍;无参构造器则是10倍。- 可变性:ArrayList是可变的数组,可以在运行时添加、删除元素。而Vector在Java 1.2之前不安全,容易导致数据丢失或错误。

请问如何构建一个高效的集合管理系统?

集合 Vector底层结构和ArrayList的比较 底层结构 版本 线程安全(同步)效率 扩容倍数 ArrayList 可变数组 jdk1.2 不安全,效率高 如果有参构造就是1.5倍扩容
如果是无参构造
1.第一次10
2.从第二次开始按1.5倍扩 Vector 可变数组Object[] jdk1.0 安全,效率不高 如果是无参,默认10,满后,就按2倍扩容
如果指定大小,则每次直接按2倍扩 ArrayList和LinkedList的比较 底层结构 增删的效率 改查的效率 ArrayList 可变数组 较低
数组扩容 较高 LinkedList 双向链表 较高
通过链表追加 较低

如何选择:

  1. 如果我们改查的操作多,选择ArrayList
  2. 如果我们增删的操作多,选择LinkedList
  3. 一般来说,再程序中,80%-90%都是查询,因此大部分情况会选择ArrayList
Set集合概述和特点

Set集合特点:

  1. 不包含重复元素的集合
  2. 没有带索引的方法,所以不能使用普通for循环遍历
HashSET底层机制说明
  1. HashSet底层是HashMap,第一次添加时,table数组扩容到16,临界值(threshold)是16*加载因子(loadFator)是0.75 = 12;
  2. 如果table数组使用到了临界值12,就会扩容到16*2 =32,新的临界值就是32*0.75 = 24,依次类推;
  3. 在java8中,如果一条链表的元素个数到达TREEIFY_THRESHOLD(默认是8),并且table大小>=MIN_TREEIFY_CAPACITY(默认是64),就会进行树化(红黑树),否则仍然采用数组扩容机制;

Map接口实现类的特点

注意:这里说的是jdk8

  1. Map用于保存具有映射关系的数据:Key-Value
  2. Map中的key和value可以是任何引用类型的数据,会封装到HashMap$Node对象中
  3. Map中的key不允许重复,原因和HashSet一样,如果有相同的key则新的value替换旧的value
  4. Map中的value可以重复
  5. Map的key可以为null,value也可以为null,注意key为null话只能有一个,value为null可以有多个;
  6. 常用String类作为Map的key
  7. key和value之间存在单向一对一关系,即通过指定的key总能找到对应的value
HashMap介绍
  1. Map接口的常用实现类:HashMap、Hashtable和Properties
  2. HashMap是Map接口使用频率最高的实现类
  3. HashMap是以key-val对应的方式来存储数据
  4. key值不能重复,但是value可以重复,允许使用null键和null值
  5. 如果添加相同的key,则会覆盖原来的key-val,等同于修改(key不会替换,val会替换)
  6. 与HashSet一样,不保证映射的顺序,因为磁层是以hash表的方式来存储的
  7. HashMap没有实现同步,因此是线程不安全的
HashTable介绍
  1. 存放的元素是键值对:k-v
  2. hashTable的键和值都不能为null,否则会抛出NullPointerException
  3. hashTable使用方法基本上和HashMap一样
  4. hashTable是线程安全的,hashMap是线程不安全的
Hashtable和HashMap对比 版本 线程安全(同步) 效率 允许null键null值 HashMap 1.2 不安全 高 可以 Hashtable 1.0 安全 较低 不可以 Properties基本介绍
  1. Properties类继承自Hashtable类并且实现了Map接口,也是使用一种键值对的形式来保存数据。
  2. 它的使用特点和Hashtable类似
  3. Properties还可以用于从xxx.properties文件中,加载数据到Properties类对象,并进行读取和修改
  4. key和value不能为null
开发中如何选择集合实现类

在开发中,选择上面集合实现类,主要取决于业务操作特点,然后根绝结合实现类特性进行选择,分析如下:

1.先判断存储的类型(一组对象[单列]或是一组键值对[双列])

2.一组对象[单列]:Collection接口

​ 允许重复:List

​ 增删多:LinkedList[底层维护了一个双向链表]

​ 改查多:ArrayList[底层维护Object类型的可变数组]

​ 不允许重复:Set

​ 无序:HashSet [底层是HashMap,维护了一个哈希表,即(数组+链表+红黑树)]

​ 排序:TreeSet

​ 插入和取出顺序一致:LinkedHashSet,维护的是数组+双向链表

3.一组键值对[双列]:Map

​ 键无序:HashMap [底层是:哈希表 jdk7:数组+链表,jdk8:数组+链表+红黑树]

​ 键排序:TreeMap

​ 键插入和取出顺序一致:LinkedHashMap

​ 读取文件:Properties

HashSet和TreeSet是如何实现去重的
  • HashSet去重机制:hashCode() + equals(),底层先通过存入对象,进行运算得到hash值,通过hash值得到对应的索引,如果发现得到的索引对应table中相同索引的位置没有数据则直接存放,如果有数据,则会进行equals比较[遍历比较],如果比较后不相同则加入,否则不加入。
  • TreeSet去重机制:如果你传入了一个Comparator匿名对象,就是用实现的compare去重,如果方法返回0,就认为是相同的元素/数据,就不添加,如果你没有传入一个Comparator匿名对象,则以你添加的对象实现的Comparable接口的compareTo去重。
分析下面代码

package com.example.homework; import java.util.HashSet; import java.util.Objects; /** * @Author 郜庆辉 * @Time 2022/5/28 17:47 * @Version 1.0 */ public class Homework4 { public static void main(String[] args) { HashSet set = new HashSet(); Person p1 = new Person(1001, "AA"); Person p2 = new Person(1002, "BB"); set.add(p1); //第一次添加的1001, "AA",p1的hash值为10 set.add(p2); System.out.println(set); p1.name = "CC"; //修改后的1001, "CC",p1的hash值还是10,只不过CC把AA占了 System.out.println(set); set.remove(p1);//remove时也会计算hash值,但是计算的是1001, "CC"的hash值;hash值为11,删除的就hash值为11的索引位置;即p1没有删除成功,因为p1的hash为10; System.out.println(set); set.add(new Person(1001, "CC"));//这里添加的是按照1001, "CC"hash值进行添加的,同样会添加成功,hash值为12; System.out.println(set); set.add(new Person(1001,"AA")); //这里又添加的1001,"AA"hash值为10,跟p1的hash值一样,按理说不会添加成功,但是现在P1是1001,"CC",hash不一样时用equals比较,value不同,也可以添加成功。 System.out.println(set); } } class Person { public int id; public String name; public Person(int id, String name) { this.id = id; this.name = name; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return id == person.id && Objects.equals(name, person.name); } @Override public int hashCode() { return Objects.hash(id, name); } // @Override // public String toString() { // return "Person{" + // "id=" + id + // ", name='" + name + '\'' + // '}'; // } } Vector和ArrayList比较 底层结构 版本 线程安全(同步)效率 扩容倍数 ArrayList 可变数组 jdk1.2 不安全,效率高 如果使用有参构造器按照1.5倍扩容,如果使用无参构造器:
1.第一次扩容10
2.从第二次开始按照1.5倍扩容 Vector 可变数组
Object[] jdk1.0 安全,效率不高 如果是无参,默认10,满后按照2倍扩容
如果是指定大小创建Vector,则每次按照2倍扩容。