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 ...
随机推荐
- 修改Anaconda中Jupyter Notebook默认工作路径
修改Anaconda中Jupyter Notebook默认工作路径 1.打开 Anaconda Prompt 2.输入命令 jupyter notebook --generate-config 这个命 ...
- 云计算管理平台之OpenStack计算服务nova
一.nova简介 nova是openstack中的计算服务,其主要作用是帮助我们在计算节点上管理虚拟机的核心服务:这里的计算节点就是指用于提供运行虚拟机实例的主机,通常像这种计算节点有很多台,那么虚拟 ...
- 彻底弄懂设置根元素字体大小calc(100vw/18.75) 实现rem自适应
rem 是相对文档根元素(html)字体大小的尺寸单位,当元素的尺寸或文字字号等使用 rem 单位时,会随着根元素的 font-size 变化而变化,那么在不同分辨率的设备下动态设置根元素的字体大小就 ...
- 调度《Taint(污点) 和 Toleration(容忍)》
节点亲和性(详见这里),是 pod 的一种属性(偏好或硬性要求),它使 pod 被吸引到一类特定的节点.Taint 则相反,它使 节点 能够 排斥 一类特定的 pod. Taint 和 tolerat ...
- (1)ASP.NET Core3.1 Ocelot介绍
1.简介 Ocelot原本设计仅为与.NET Core一起使用的,它是一个.NET API网关,作为面向使用.NET运行微型服务/面向服务的体系结构需要统一的系统入口点,即当客户端(Web站点,手机A ...
- 《为研发同学定制的MySQL面试指南》-- 连载中
Hi大家好,我是来自博客园的赐我白日梦! 为大家带来MySQL面试专题!全文110篇!以问答的方式,由浅入深的帮你应对各类MySQL面试题的狂轰滥炸!当然也不乏会分享一些高阶读写分离数据库中间件原理及 ...
- Linux 软件安装的三种方式
Linux 软件安装的三种方式 1.yum 语法格式: yum -y install package.name -y yes # 遇到提示自动输入yes 案例: 安装ifconfig命 ...
- Java8 新特性 —— Stream 流式编程
本文部分摘自 On Java 8 流概述 集合优化了对象的存储,大多数情况下,我们将对象存储在集合是为了处理他们.使用流可以帮助我们处理对象,无需迭代集合中的元素,即可直接提取和操作元素,并添加了很多 ...
- IP 层收发报文简要剖析4--ip 报文发送
无论是从本地输出的数据还是转发的数据报文,经过路由后都要输出到网络设备,而输出到网络设备的接口就是dst_output(output)函数 路由的时候,dst_output函数设置为ip_output ...
- jsp 和servlet基础知识
1 在tomcat服务器当中,4**表示客户端请求错误,5**表示程序错误 2.request知识参考网址:http://wenku.baidu.com/link?url=wYwTGk8XKrLzA ...