Set
- Set:一个不包含重复元素的 collection。
* 更确切地讲,set 不包含满足 e1.equals(e2) 的元素对 e1 和 e2,并且最多包含一个 null 元素。
* 父接口:Collection
* 实现类:HashSet,TreeSet,LinkedHashSet
* 从以下版本开始: 1.2
* set特点:无序且唯一,只能添加一个null元素
import java.util.HashSet;
import java.util.Set;
public class Demo {
public static void main(String[] args) {
//1:创建一个Set集合
Set<String> set = new HashSet<>();
//2:添加元素
set.add("a");
set.add("a");
set.add("b");
set.add("c");
set.add(null);
set.add(null);
System.out.println(set);
}
}
HashSet
- HashSet:此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。
* 它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。
* 特点:无序且唯一,允许使用null元素,但是只能有一个null元素
* 注意,此实现不是同步的。
* 父接口:List
* 父类:AbstractSet
* 子类:LinkedHashSet
* 从以下版本开始: 1.2
*
* 哈希表结构:是一种特殊的数据结构,数组+链表
* 数组保证了查询速度快
* 链表保证了增删速度快
* 底层是以键值对的形式存放数据
* key–value
* 101–张三
* 102–张三
* 注意:key不能重复,但是value是可以重复的
*
* hashSet:第一次添加元素的时候给了一个默认16的数组结构
*
*
* HashSet特点
* 无序:底层要使用当前元素的hashCode和数组的长度-1做&运算,结果就是存放的数组的下表位置
* 唯一:
* 前提:判断对象是否相等,首先判断2个对象的hashCode以及equals是否相等,
* 如果相等,最后胡返回一个有值的对象,通过这个对象和null做==比较,结果为false,
* 所以重复的元素添加不进去
*
* 注意:如果数组下标中的链接节点超过8个,jdk1.8采用了新的二叉树结构数据结构,
* 什么时候数组扩容
* 第一次:元素个数超过12的时候,
* 第二次:元素个数超过24的时候,
* 依次类推…
import java.util.ArrayList;
import java.util.HashSet;
public class Demo {
public static void main(String[] args) {
//1:创建一个HashSet集合
HashSet<String> hs = new HashSet<>();
//2:添加元素
hs.add("a");
hs.add("aa");
hs.add("ab");
hs.add("a");
hs.add("你");
hs.add("好");
hs.add("吗");
hs.add("中");
hs.add("过");
hs.add("人");
hs.add("谭");
hs.add("剑");
hs.add("电");
hs.add("脑");
hs.add("手");
hs.add("机");
hs.add("王");
System.out.println(hs);
//System.out.println(("aa".hashCode())&15);
//putVal(97, "a",new Object(), false, true);
System.out.println(("脑".hashCode())&15);
}
}
HashSetDemo2
- HashSet去除重复的自定义对象
*
* 在java中属性值完全的相同的对象我们称为重复的对象
*
* hashCode选用31的原理
* 1.基数要用质数
* 质数的特性(只有1和自己是因子)能够使得它和其他数相乘后得到的结果比其他方式更容易产成唯一性,也就是hash code值的冲突概率最小。
* 2.选择31是观测分布结果后的一个选择,不清楚原因,但的确有利
import java.util.HashSet;
import java.util.Iterator;
public class Demo {
public static void main(String[] args) {
//1:创建Student集合
HashSet<Student> hs = new HashSet<>();
//2:添加学生
hs.add(new Student("张三", 20, "男"));
hs.add(new Student("李四", 20, "女"));
hs.add(new Student("王五", 30, "男"));
hs.add(new Student("张三", 20, "男"));
System.out.println(new Integer(20).hashCode());
System.out.println("男".hashCode());
//3:遍历集合
for (Student stu : hs) {
System.out.println(stu);
}
System.out.println((24100577) ^ (24100577 >>> 16));
System.out.println(1023480028&15);
}
}
public class Student {
private String name;
private Integer age;
private String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Student(String name, Integer age, String sex) {
super();
this.name = name;
this.age = age;
this.sex = sex;
}
public Student() {
super();
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", sex=" + sex + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((age == null) ? 0 : age.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((sex == null) ? 0 : sex.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age == null) {
if (other.age != null)
return false;
} else if (!age.equals(other.age))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (sex == null) {
if (other.sex != null)
return false;
} else if (!sex.equals(other.sex))
return false;
return true;
}
}
LinkedHashSet
- LikedHashSet
* 具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现。
* 此实现与 HashSet 的不同之外在于,后者维护着一个运行于所有条目的双重链接列表。
* 父类:HashSet
* 父接口:Set
* 注意,此实现不是同步的。
* 从以下版本开始: 1.4
import java.util.HashSet;
import java.util.LinkedHashSet;
public class Demo {
public static void main(String[] args) {
HashSet<Integer> hs = new HashSet<>();
hs.add(10);
hs.add(20);
hs.add(30);
hs.add(40);
hs.add(10);
System.out.println(hs);
//既能去除重复,而且还是有序的(添加顺序和迭代顺序一致)
LinkedHashSet<Integer> lhs = new LinkedHashSet<>();
lhs.add(10);
lhs.add(20);
lhs.add(30);
lhs.add(40);
lhs.add(10);
System.out.println(lhs);
}
}