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因为要维护红黑树,效率较低。

最新文章

  1. [转]大数据时代,python竟是最好的语言?
  2. BZOJ4590——[Shoi2015]自动刷题机
  3. Oralce sysaux WRH$_ACTIVE_SESSION_HISTORY清理
  4. 费用流 ZOJ 3933 Team Formation
  5. HDU 2254
  6. C#调用dll提示&quot;试图加载格式不正确的程序&quot;解决方法
  7. javascript onload队列
  8. 甚是挂念学校的acmer
  9. FileOutputStream和FileInputStream
  10. [DP] Rod-cutting problem
  11. windows 下解决 Time_Wait 和 CLOSE_WAIT 方法
  12. struts+hibernate 请求数据库增删改查(小项目实例)
  13. 探究Java中Map类
  14. 新一代的昆明网络seo优化技巧
  15. element vue validate验证名称重复 输入框与后台重复验证 特殊字符 字符长度 及注意事项
  16. mac 安装yarn失败
  17. OpenJudge Cartesian Tree
  18. POJ 2242 The Circumference of the Circle
  19. Charles安装包及破解包下载地址
  20. Flash的不同位宽与CPU地址线的接线问题?

热门文章

  1. U138097 小鱼吃大鱼 埃氏筛
  2. drf 路由生成
  3. Hadoop高可用
  4. 《Clojure编程》笔记 第5章 宏
  5. python pip源国内加速
  6. 用DOM和DOM4J写xml文件时,怎样设置xml文档的编码
  7. JSP系列记录
  8. C++ 基础 3:类和对象
  9. 1+X云计算平台运维与开发(中级)eNSP A~E卷 试题+答案
  10. Spider_基础总结1_Request(get/post__url传参_headers_timeout)+Reponse