当前位置 : 主页 > 编程语言 > 其它开发 >

集合

来源:互联网 收集:自由互联 发布时间:2022-06-06
集合Vector底层结构和ArrayList的比较 底层结构 版本 线程安全(同步)效率 扩容倍数 ArrayList可变数组jdk1.2不安全,效率高如果有参构造就是1.5倍扩容 如果是无参构造 1.第一次10 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倍扩容。
上一篇:vue3.2新增指令v-memo的使用
下一篇:没有了
网友评论