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的更多相关文章

  1. Java基础教程(18)--继承

    一.继承的概念   继承是面向对象中一个非常重要的概念,使用继承可以从逻辑和层次上更好地组织代码,大大提高代码的复用性.在Java中,继承可以使得子类具有父类的属性和方法或者重新定义.追加属性和方法. ...

  2. Java基础教程(12)--深入理解类

    一.方法的返回值   当我们在程序中调用方法时,虚拟机将会跳转到对应的方法中去执行.当以下几种情况发生时,虚拟机将会回到调用方法的语句并继续向下执行: 执行完方法中所有的语句: 遇到return语句: ...

  3. Java基础教程:注解

    Java基础教程:注解 本篇文章参考的相关资料链接: 维基百科:https://zh.wikipedia.org/wiki/Java%E6%B3%A8%E8%A7%A3 注解基础与高级应用:http: ...

  4. Java基础教程:网络编程

    Java基础教程:网络编程 基础 Socket与ServerSocket Socket又称"套接字",网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个s ...

  5. Java基础教程(5)--变量

    一.变量 1.变量的定义   正如上一篇教程<Java基础教程(4)--面向对象概念>中介绍的那样,对象将它的状态存在域中.但是你可能仍然有一些疑问,例如:命名一个域的规则和惯例是什么?除 ...

  6. Java基础教程:Lambda表达式

    Java基础教程:Lambda表达式 本文部分内容引用自OneAPM:http://blog.oneapm.com/apm-tech/226.html 引入Lambda Java 是一流的面向对象语言 ...

  7. Java基础教程:泛型基础

    Java基础教程:泛型基础 引入泛型 传统编写的限制: 在Java中一般的类和方法,只能使用具体的类型,要么是基本数据类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制就会束缚 ...

  8. Java基础教程:多线程基础(1)——基础操作

    Java:多线程基础(1) 实现多线程的两种方式 1.继承Thread类 public class myThread extends Thread { /** * 继承Thread类,重写RUN方法. ...

  9. Java基础教程:反射基础

    Java基础教程:反射基础 引入反射 反射是什么 能够动态分析类能力的程序称为反射. 反射是一种很强大且复杂的机制. Class类 在程序运行期间,Java运行时系统始终为所有对象维护一个被称为运行时 ...

  10. Java基础教程:多线程基础(4)——Lock的使用

    Java基础教程:多线程基础(4)——Lock的使用 快速开始 Java 5中Lock对象的也能实现同步的效果,而且在使用上更加方便. 本节重点的2个知识点是:ReentrantLock类的使用和Re ...

随机推荐

  1. NB-IoT的HARQ过程是怎么样的

    NB-IoT的HARQ是一种将前向纠错(Forward Error Correction,FEC)编码和ARQ相结合而形成的技术.HARQ的基本原理是缓存没有正确接收到的数据,并且将重传数据和原始数据 ...

  2. Go--关于 goroutine、channel

    Go--关于 goroutine.channel goroutine 协程是一种轻量化的线程,由Go编译器进行优化. Go协程具有以下特点: 有独立的栈空间 共享程序堆中的空间 调度由用户控制 如果主 ...

  3. ES6--数组部分基础知识

    数组Array的相关方法 1.Array.from()方法 Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象 ...

  4. SpringBoot第五集:整合监听器/过滤器和拦截器(2020最新最易懂)

    SpringBoot第五集:整合监听器/过滤器和拦截器(2020最新最易懂) 在实际开发过程中,经常会碰见一些比如系统启动初始化信息.统计在线人数.在线用户数.过滤敏/高词汇.访问权限控制(URL级别 ...

  5. TCP 队列溢出了

    一.TCP 队列 1.syns queue:半连接队列 TCP 三次握手(参考:TCP建立连接之三次握手),第一步,服务端接收到客户端发送的 syn 消息后,将连接信息放入 syns queue,此时 ...

  6. Nginx跳转配置

    1.携带目录调转到后端,后端无目录,location配置如下 例子: i2.jusdacfj.com/ideas_edi/--10.0.2.137:7040/10.0.2.138:7040 locat ...

  7. MySQL各版本connector net msi

    从其他博主那里扒来的! 链接:https://pan.baidu.com/s/1C1fYepBFKfxU0NJS0aRyJw 提取码:awsl

  8. MIPS学习笔记(一)

    写在前面 本文是根据"MIPS Assembly Language Programming CS50 Discussion and Project Book. Daniel J. Ellar ...

  9. 实验3ss

    1.实验任务1 #include <math.h> #include <stdio.h> int main() { float a,b,c,x1,x2; float delta ...

  10. Redis下载

    Windows版下载地址 https://github.com/tporadowski/redis/releases Linux版下载地址 https://redis.io/download