Java基础教程——Set
Set·无序,不重复

HashSet
特点:没有重复数据,数据不按存入的顺序输出。
HashSet由Hash表结构支持。不支持set的迭代顺序,不保证顺序。
但是Hash表结构查询速度很快。
创建集合使用代码:
Set<String> s = new HashSet<>();
代码演示:常用方法和遍历输出
import java.util.*;
public class TestHashSet {
public static void main(String[] args) {
m010赋值And遍历();
}
public static void m010赋值And遍历() {
System.out.println("=====赋值And遍历");
Set<String> s = new HashSet<>();
s.add("孙悟空");
s.add("小白龙");
s.add("猪八戒");
s.add("沙悟净");
s.add("孙悟空");
System.out.println("是否为空:" + s.isEmpty());
System.out.println("是否包含:" + s.contains("小白龙"));
System.out.println("移除:" + s.remove("小白龙"));
// (1)foreach:遍历set
for (String str : s) {
System.out.println(str);
}
// (2)迭代器:遍历set
Iterator<String> it = s.iterator();
while (it.hasNext()) {
String str = it.next();
System.out.println("Iterator : " + str);
}
// (3)*Java 8新增遍历方法
s.forEach(elm -> System.out.println("Lambda:" + elm));
}
}
Hash和Hash表
Hash
HashCode,是一个十进制整数,是对象的地址值(逻辑地址,不是物理地址)
Object类有一个方法,可以获取对象的Hash值。
public native int hashCode();
String重写了hashCode方法
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
以至于有些不同字符串的hashCode相等(字符串还是不等的,无论==还是equals):
System.out.println("重地".hashCode());
System.out.println("通话".hashCode());
System.out.println("--------------");
System.out.println("方面".hashCode());
System.out.println("树人".hashCode());
System.out.println("--------------");
System.out.println("儿女".hashCode());
System.out.println("农丰".hashCode());
System.out.println("--------------");
System.out.println("Ea".hashCode());
System.out.println("FB".hashCode());
Hash表
Java8之前:Hash表使用数组+链表;
Java8之后加入了红黑树,查询速度加快。
Hash表结构的示意图如下所示:
数组里存储的是HashCode。
HashCode相同的元素加入相同链表;
如果链表长度超过8,就转为红黑树以提高查询速度。

怎么才算重复?
HashSet中,元素不重复指“equals方法比较为true,且hashCode不同”。
下列示例代码中,只有equals为true、且hashCode相同的对象未重复存入Set中。
import java.util.*;
class A_equalsT {
public boolean equals(Object obj) {
return true;
}
}
class B_hash1 {
public int hashCode() {
return 1;
}
}
class C_hash2_equalsT {
public int hashCode() {
return 2;
}
public boolean equals(Object obj) {
return true;
}
}
public class TestSet怎么才算重复 {
public static void main(String[] args) {
Set<Object> _set = new HashSet<Object>();
_set.add(new A_equalsT());
_set.add(new A_equalsT());
_set.add(new B_hash1());
_set.add(new B_hash1());
_set.add(new C_hash2_equalsT());
_set.add(new C_hash2_equalsT());
for (Object object : _set) {
System.out.println(object);
}
}
}
运行结果:(C_hash2_equalsT只存入一份,说明被看作重复对象)
B_hash1@1
B_hash1@1
C_hash2_equalsT@2
A_equalsT@15db9742
A_equalsT@6d06d69c
HashSet存储自定义元素时,需要重写hashCode和equals方法,才能保证集合中对象的唯一性。
练习:
创建Student类,至少需要包含id、name。创建多个Student对象加入HashSet,如果学号(id)相同则不重复加入。
TreeSet
TreeSet支持两种排序方式,自然排序和定制排序。默认为自然排序,和HashSet的输出顺序不一样。
TreeSet使用红黑树存储元素(示例和下一小节一起)。
LinkedHashSet
Set也可以有序,这个LinkedHashSet就能按照输入顺序输出结果。
LinkedHashSet也是根据元素的hashCode值决定元素的存储位置,但是加了一条链表记录元素的存储顺序,这使得元素有序。
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;
public class TestTree{
public static void main(String[] args) {
m020各种Set();
}
private static void m020各种Set() {
System.out.println("|-HashSet:");
Set<String> _set;
_set = new HashSet<String>();
_set.add("B");
_set.add("A");
_set.add("1");
_set.add("2");
_set.add(null);
printSet(_set);
System.out.println("|-TreeSet不接受空值:");
_set = new TreeSet<String>();
_set.add("B");
_set.add("A");
_set.add("1");
_set.add("2");
// _set.add(null);
printSet(_set);
System.out.println("|-LinkedHashSet:有序");
_set = new LinkedHashSet<String>();
_set.add("B");
_set.add("A");
_set.add("1");
_set.add("2");
_set.add(null);
printSet(_set);
}
private static void printSet(Set<String> _set) {
for (String str : _set) {
System.out.print(str + " ");
}
System.out.println();
}
}
|-HashSet:
null A 1 B 2
|-TreeSet不接受空值:
1 2 A B
|-LinkedHashSet:有序
B A 1 2 null
Set的性能
HashSet综合效率最高,LinkedHashSet因为有链表,遍历时会更快一些。TreeSet因为要维护红黑树,效率较低。
Java基础教程——Set的更多相关文章
- Java基础教程(18)--继承
一.继承的概念 继承是面向对象中一个非常重要的概念,使用继承可以从逻辑和层次上更好地组织代码,大大提高代码的复用性.在Java中,继承可以使得子类具有父类的属性和方法或者重新定义.追加属性和方法. ...
- Java基础教程(12)--深入理解类
一.方法的返回值 当我们在程序中调用方法时,虚拟机将会跳转到对应的方法中去执行.当以下几种情况发生时,虚拟机将会回到调用方法的语句并继续向下执行: 执行完方法中所有的语句: 遇到return语句: ...
- Java基础教程:注解
Java基础教程:注解 本篇文章参考的相关资料链接: 维基百科:https://zh.wikipedia.org/wiki/Java%E6%B3%A8%E8%A7%A3 注解基础与高级应用:http: ...
- Java基础教程:网络编程
Java基础教程:网络编程 基础 Socket与ServerSocket Socket又称"套接字",网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个s ...
- Java基础教程(5)--变量
一.变量 1.变量的定义 正如上一篇教程<Java基础教程(4)--面向对象概念>中介绍的那样,对象将它的状态存在域中.但是你可能仍然有一些疑问,例如:命名一个域的规则和惯例是什么?除 ...
- Java基础教程:Lambda表达式
Java基础教程:Lambda表达式 本文部分内容引用自OneAPM:http://blog.oneapm.com/apm-tech/226.html 引入Lambda Java 是一流的面向对象语言 ...
- Java基础教程:泛型基础
Java基础教程:泛型基础 引入泛型 传统编写的限制: 在Java中一般的类和方法,只能使用具体的类型,要么是基本数据类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制就会束缚 ...
- Java基础教程:多线程基础(1)——基础操作
Java:多线程基础(1) 实现多线程的两种方式 1.继承Thread类 public class myThread extends Thread { /** * 继承Thread类,重写RUN方法. ...
- Java基础教程:反射基础
Java基础教程:反射基础 引入反射 反射是什么 能够动态分析类能力的程序称为反射. 反射是一种很强大且复杂的机制. Class类 在程序运行期间,Java运行时系统始终为所有对象维护一个被称为运行时 ...
- Java基础教程:多线程基础(4)——Lock的使用
Java基础教程:多线程基础(4)——Lock的使用 快速开始 Java 5中Lock对象的也能实现同步的效果,而且在使用上更加方便. 本节重点的2个知识点是:ReentrantLock类的使用和Re ...
随机推荐
- python文件命名时的注意点
在python中读取Excal文件,需要引用xlrd模块,因此建的这个python文件名为xlrd.py 部分代码如下: import xlrd import os newpath = os.chdi ...
- 4G DTU的使用方法和应用领域
4G DTU是一种数据传输单元,通俗理解就是,用来传输数据的一种硬件.既然是用来传输数据的,那就能将它视为一个管道,也就是说,指令同过它传给设备,而管道是不对这些指令做出响应的. 4G DTU如何使用 ...
- shell脚本之字符串测试表达式
1.字符串测试操作符 字符串测试操作符的作用有:比较两个字符串是否相同.字符串的长度是否为零,字符串是否为NULL(注:bash区分零长度字符串和空字符串等) 下表为常用字符串操作符 也可以通过man ...
- Windows10系统下Hadoop和Hive开发环境搭建填坑指南
前提 笔者目前需要搭建数据平台,发现了Windows系统下,Hadoop和Hive等组件的安装和运行存在大量的坑,而本着有坑必填的目标,笔者还是花了几个晚上的下班时候在多个互联网参考资料的帮助下完成了 ...
- 分四个阶段学习python并找到一份好工作
第一阶段 关注公众号"轻松学编程"了解更多. 详细学习资料 需要时间一个月. 1.python概念 python是一种解释型.面向对象.动态数据类型的高级程序语言. 理解: ...
- ASP.NET Core Authentication系列(四)基于Cookie实现多应用间单点登录(SSO)
前言 本系列前三篇文章分别从ASP.NET Core认证的三个重要概念,到如何实现最简单的登录.注销和认证,再到如何配置Cookie 选项,来介绍如何使用ASP.NET Core认证.感兴趣的可以了解 ...
- import tensorflow 出现非法指令(核心已转储)
使用 conda install -c conda-forge tensorflow 或者 conda install -c conda-forge tensorflow-gpu 试下.
- 使用 C# 9.0 新语法提升 if 语句美感
C# 语言一贯秉承简洁优美的宗旨,每次升级都会带来一些语法糖,让我们可以使代码变得更简洁.本文分享两个使用 C# 9.0 提升 if 语句美感的技巧示例. 使用属性模式代替 IsNullOrEmpty ...
- 三十二张图告诉你,Jenkins构建Spring Boot 有多简单~
持续原创输出,点击上方蓝字关注我 目录 前言 如何安装Jenkins? 环境准备 开始安装Jenkins 初始化配置 访问首页 输入管理员密码 安装插件 创建管理员 实例配置 配置完成 构建Sprin ...
- [MIT6.006] 9. Table Doubling, Karp-Rabin 双散列表, Karp-Rabin
在整理课程笔记前,先普及下课上没细讲的东西,就是下图,如果有个操作g(x),它最糟糕的时间复杂度为Ο(c2 * n),它最好时间复杂度是Ω(c1 * n),那么θ则为Θ(n).简单来说:如果O和Ω可以 ...