java基础---集合(2)
一、 Set 集合
- java.util.Set集合是Collection集合的子集合,与List集合平级。该集合中元素没有先后放入次序,且不允许重复。
- 存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数据的哈希值决定的
- 保证添加的元素按照equals()判断时,不能返回true.即:相同的元素只能添加一个
- 该集合的主要实现类是:HashSet类 和 TreeSet类以及LinkedHashSet类。
- HashSet类的底层是采用哈希表进行数据管理的,数组+链表
- TreeSet类的底层是采用红黑树进行数据管理的
- LinkedHashSet类与HashSet类的不同之处在于内部维护了一个双向链表,链表中记录了元素的迭代顺序,也就是元素插入集合中的先后顺序,因此便于迭代。
- Set接口中没有额外定义新的方法,使用的都是Collection中声明过的方法
1. HashSet
- 底层是采用哈希表进行数据管理的,数组+链表,数组初始容量为16, 当如果使用率超过0.75,就会扩大容量为原来的2倍;不能保证元素的排列顺序,非线程安全,集合元素可以为null
- 为什么用Eclipse/IDEA复写hashCode方法,有31这个数字?
- 选择系数的时候要选择尽量大的系数。因为如果计算出来的hash地址越大,所谓的“冲突”就越少,查找起来效率也会提高。(减少冲突)
- 31只占用5bits,相乘造成数据溢出的概率较小。
- 31可以 由i*31== (i<<5)-1来表示,现在很多虚拟机里面都有做相关优化。 (提高算法效率)
- 31是一个素数,素数作用就是如果我用一个数字来乘以这个素数,那么最终出来的结果只能被素数本身和被乘数还有1来整除! (减少冲突)
- 添加元素的过程
- 我们向HashSet中添加元素a,首先调用元素a所在类的hashCode()方法,计算元素a的哈希值,此哈希值接着通过某种算法计算出在HashSet底层数组中的存放位置(即为:索引位置),判断数组此位置上是否已经有元素
如果此位置上没有其他元素,则元素a添加成功。 --->情况1
如果此位置上有其他元素b(或以链表形式存在的多个元素),则比较元素a与元素b的hash值:
如果hash值不相同,则元素a添加成功。--->情况2
如果hash值相同,进而需要调用元素a所在类的equals()方法:equals()返回true,元素a添加失败;equals()返回false,则元素a添加成功。--->情况2
对于添加成功的情况2和情况3而言:元素a 与已经存在指定索引位置上数据以链表的方式存储。
jdk 7 :元素a放到数组中,指向原来的元素。
jdk 8 :原来的元素在数组中,指向元素a
2. LinkedHashSet
- 根据元素的 hashCode 值来决定元素的存储位置,但它同时使用双向链表维护元素的次序,这使得元素看起来是以插入顺序保存的
- LinkedHashSet 不允许集合元素重复
- 向Set添加的数据,其所在的类一定要重写hashCode()和equals(),相等的对象必须具有相等的散列码;对象中用作 equals() 方法比较的 Field,都应该用来计算 hashCode 值。
3. TreeSet
- 底层采用红黑树进行数据的管理,当有新元素插入到TreeSet集合时,需要使用新元素与集合中已有的元素依次比较来确定新元素的合理位置
- 比较元素大小的规则有两种方式:
- 使用元素的自然排序规则进行比较并排序,让元素类型实现java.lang.Comparable接口;
- BigDecimal、 BigInteger 以及所有的数值型对应的包装类:按它们对应的数值大小进行比较
- Character:按字符的 unicode值来进行比较
- Boolean: true 对应的包装类实例大于 false 对应的包装类实例
- String:按字符串中字符的 unicode 值进行比较
- Date、 Time:后边的时间、日期比前面的时间、日期大
- 使用比较器规则进行比较并排序,构造TreeSet集合时传入java.util.Comparator接口;
- 自然排序的规则比较单一,而比较器的规则比较多元化,而且比较器优先于自然排序;
- 使用元素的自然排序规则进行比较并排序,让元素类型实现java.lang.Comparable接口;
@Test
public void tes1(){
HashSet set = new HashSet();
Person p1 = new Person(1001,"AA");
Person p2 = new Person(1002,"BB");
set.add(p1);
set.add(p2);
p1.name = "CC";
set.remove(p1); //找不到new Person(1001,"AA");
System.out.println(set);//[Person{name='CC', id=1001}, Person{name='BB', id=1002}]
set.add(new Person(1001,"CC"));
System.out.println(set);//[Person{name='CC', id=1001}, Person{name='CC', id=1001}, Person{name='BB', id=1002}]
set.add(new Person(1001,"AA"));
System.out.println(set);//[Person{name='CC', id=1001}, Person{name='CC', id=1001}, Person{name='AA', id=1001}, Person{name='BB', id=1002}]
}
class Person{
public String name;
public int id; public Person(int id,String name) {
this.name = name;
this.id = id;
} @Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", id=" + id +
'}';
} @Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; if (id != person.id) return false;
return name != null ? name.equals(person.name) : person.name == null;
} @Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + id;
return result;
}
}
二、Map集合
- java.util.Map<K,V>集合中存取元素的基本单位是:单对元素,其中类型参数如下:
- K - 此映射所维护的键(Key)的类型,相当于目录。
- V - 映射值(Value)的类型,相当于内容。该集合中key是不允许重复的,而且一个key只能对应一个value。
- 该集合的主要实现类有:HashMap类、TreeMap类、LinkedHashMap类、Hashtable类、Properties类。
- HashMap类的底层是采用哈希表进行数据管理的。
- TreeMap类的底层是采用红黑树进行数据管理的。
- LinkedHashMap类与HashMap类的不同之处在于内部维护了一个双向链表,链表中记录了元素的迭代顺序,也就是元素插入集合中的先后顺序,因此便于迭代。
- Hashtable类是古老的Map实现类,与HashMap类相比属于线程安全的类,且不允许null作为key或者value的数值。
- Properties类是Hashtable类的子类,该对象用于处理属性文件,key和value都是String类型的。
- Map集合是面向查询优化的数据结构, 在大数据量情况下有着优良的查询性能。经常用于根据key检索value的业务场景。
| 方法声明 | 功能介绍 |
| V put(K key, V value) | 将Key-Value对存入Map,若集合中已经包含该Key,则替换该Key所对应的Value,返回值为该Key原来所对应的Value,若没有则返回null |
| V get(Object key) | 返回与参数Key所对应的Value对象,如果不存在则返回null |
| boolean containsKey(Object key); | 判断集合中是否包含指定的Key |
| boolean containsValue (Object value); | 判断集合中是否包含指定的Value |
| V remove(Object key) | 根据参数指定的key进行删除 |
| Set keySet() | 返回此映射中包含的键的Set视图 |
| Collection values() | 返回此映射中包含的值的Set视图 |
| Set<Map.Entry<K,V>> entrySet() | 返回此映射中包含的映射的Set视图 |
- 使用元素的key调用hashCode方法获取对应的哈希码值,再由某种哈希算法计算在数组中的索引位置。若该位置没有元素,则将该键值对直接放入即可。
- 若该位置有元素,则使用key与已有元素依次比较哈希值,若哈希值不相同,则将该元素直接放入。
- 若key与已有元素的哈希值相同,则使用key调用equals方法与已有元素依次比较。
- 若相等则将对应的value修改,否则将键值对直接放入即可
- DEFAULT_INITIAL_CAPACITY : HashMap的默认容量是16。
- DEFAULT_LOAD_FACTOR:HashMap的默认加载因子是0.75。
- threshold:扩容的临界值,该数值为:容量*填充因子,也就是12。
- TREEIFY_THRESHOLD:若Bucket中链表长度大于该默认值则转化为红黑树存储,该数值是8。
- MIN_TREEIFY_CAPACITY:桶中的Node被树化时最小的hash表容量,该数值是64
java.util.Collections类主要提供了对集合操作或者返回集合的静态方法。
| 方法声明 | 功能介绍 |
| static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) |
根据元素的自然顺序返回给定集 合的最大元素 |
| static T max(Collection<? extends T> coll, Comparator<? super T> comp) |
根据指定比较器引发的顺序返回 给定集合的最大元素 |
| static <T extends Object & Comparable<?super T>> T min(Collection<? extends T> coll) |
根据元素的自然顺序返回给定集 合的最小元素 |
| static T min(Collection<? extends T> coll, Comparator<? super T> comp) |
根据指定比较器引发的顺序返回 给定集合的最小元素 |
| static void copy(List<? super T> dest, List<? extends T> src) |
将一个列表中的所有元素复制到 另一个列表中 |
| 方法声明 | 功能介绍 |
| static void reverse(List<?> list) | 反转指定列表中元素的顺序 |
| static void shuffle(List<?> list) | 使用默认的随机源随机置换指定的列表 |
| static <T extends Comparable<? super T>> void sort(List list) |
根据其元素的自然顺序将指定列表按升 序排序 |
| static void sort(List list, Comparator<? super T> c) | 根据指定比较器指定的顺序对指定列表 进行排序 |
| static void swap(List<?> list, int i, int j) | 交换指定列表中指定位置的元素 |
java基础---集合(2)的更多相关文章
- JAVA基础-集合(二)
一.Map整体结构体系 Map是集合的另一大派系,与Collection派系不同的是Map集合是以键值对儿的形式存储在集合的.两个键为映射关系,其中第一个键为主键(主键是唯一的不可重复),第二个键为v ...
- Java基础-集合的嵌套
Java基础-集合的嵌套 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.静态导入 静态导入是在JDK1.5后的新特性,可以减少开发的代码量,但是实际用处是很一般,静态导入的标准 ...
- Java基础——集合框架
Java的集合框架是Java中很重要的一环,Java平台提供了一个全新的集合框架.“集合框架”主要由一组用来操作对象的接口组成.不同接口描述一组不同数据类型.Java平台的完整集合框架如下图所示: 上 ...
- java基础---集合(1)
一. 基本概念 集合.数组都是对多个数据进行存储操作的结构,简称Java容器 数组:长度确定,类型确定,对于添加.删除.插入等操作效率不高,元素有序可重复 Java中集合框架顶层框架是:java.ut ...
- Java基础——集合源码解析 List List 接口
今天我们来学习集合的第一大体系 List. List 是一个接口,定义了一组元素是有序的.可重复的集合. List 继承自 Collection,较之 Collection,List 还添加了以下操作 ...
- Java基础—集合
一.概述 Java中的集合框架主要分为两大派别:Collection 和 Map —— 位于util包下 类的基础关系图如下(图片来自百度) 常用: List——有序可重复 Set——无序不可重复 M ...
- java基础集合简介Set(三)中
今天主要说夏set集合,每天抽出一个小时总结下,生活会更加美好! --< java.util >-- Set接口: 数据结构:数据的存储方式: Set接口中的方法和Collection中方 ...
- java基础集合经典训练题
第一题:要求产生10个随机的字符串,每一个字符串互相不重复,每一个字符串中组成的字符(a-zA-Z0-9)也不相同,每个字符串长度为10; 分析:*1.看到这个题目,或许你脑海中会想到很多方法,比如判 ...
- 十七、Java基础---------集合框架之Map
前两篇文章中介绍了Collection框架,今天来介绍一下Map集合,并用综合事例来演示. Map<K,V> Map<K,V>:Map存储的是键值对形式的元素,它的每一个元素, ...
- 十六、Java基础---------集合框架之Set
写在前面的话,这篇文章在昨天就写好了,今天打开的时候一不小心将第二天的文章粘贴到了这篇文章,很不幸的是除了标题之外依然面目全非,今天带着沉痛的心情再来写这篇文章! 上篇文章介绍了Collection体 ...
随机推荐
- PTH的几种食用姿势
PTH PTH(pass the hash)也叫做hash传递.在内网渗透中是一种很经典的攻击方式,原理就是攻击者可以直接通过NTLM Hash(mimikatz或其他手段抓取到的密码hash)访问远 ...
- python mixin到底是什么
python mixin到底是什么 1.什么是Mixin 在面向对象编程中,Mixin是一种类,这种类包含了其他类要使用的方法,但不必充当其他类的父类.其他类是如何获取Mixin中的方法因语言的不同而 ...
- 内建函数 iter()
可以选择接受一个无参的可调用对象以及一个哨兵(结束)作为输入.当已这种方式使用时,iter()会创建i一个迭代器,然后重复调用用户提供的可调用对象,直到返回哨兵的值为止. import sys wit ...
- Java | Stream流、泛型、多线程 | 整理自用
1.lambda 表达式 lambda 的延迟执行 可以对程序进行优化,尤其是使用 if {} else {} 条件判断,先判断条件是否成立,再传入计算好的参数. functionName( para ...
- javascript获取日期,年月,日
<SCRIPT LANGUAGE="JavaScript"> var myDate = new Date(); myDate.getYear(); ...
- TVM编译机器学习到 WASM 和 WebGPU
TVM编译机器学习到 WASM 和 WebGPU TLDR TVM 深度学习编译器对 WASM 和 WebGPU 的支持.实验表明,TVM 的 WebGPU 后端在将模型部署到 Web 时可以接近原生 ...
- 【译】.NET 5 中的诊断改进
基于我们在 .NET Core 3.0 中引入的诊断改进,我们一直在努力进一步改进这个领域.我很高兴介绍下一波诊断改进. 诊断工具不再需要 .NET SDK 直到最近,.NET 诊断工具套件还只能作为 ...
- 「题解」300iq Contest 2 B Bitwise Xor
本文将同步发布于: 洛谷博客: csdn: 博客园: 简书. 题目 题目链接:gym102331B. 题意概述 给你一个长度为 \(n\) 的序列 \(a_i\),求一个最长的子序列满足所有子序列中的 ...
- Task00:绪论 - 环境搭建
本章重点: 在电脑上安装MySQL数据库系统 安装客户端并连接到本机上的MySQL数据库 使用提供的脚本创建本教程所使用的示例数据库 1. MySQL 8.0 的安装 考虑到大家所使用的操作系统的不同 ...
- C# Net Core 使用 itextsharp.lgplv2.core 把Html转PDF
C# Net Core 使用 itextsharp.lgplv2.core 把Html转PDF 只支持英文(中文我不知道怎么弄,懂的朋友帮我看一下)!!!!![补充:评论区的小伙伴已解决] 引入包it ...