Set接口也是Collection接口的子类,其最大特点是不允许有重复数据出现,其继承了所有方法,HashSet集合则实现了Set接口,其内部存储数据时依靠哈希表,一个类似数组和链表的结合体。设置空集合时,存在默认的容量和加载因子,再用HashSet对象调用add方法时,其实是先比较其Hash值,若是没有的话,则直接添加到集合中,若有的话,则再equals下比较其内容(因为有可能内容不一样,但是其Hash值一样),若是内容不一样,则在这个地址下添加(链式),若是一样的话,则丢掉。注意就保证了其的唯一性。(以后定义变量时,都需要重写其hashcode和equals方法)。
自定义类使用HashSet接口:
public class Users {
private String nameString;
private int age;
public Users() {
super();
}
public Users(String nameString, int age) {
super();
this.nameString = nameString;
this.age = age;
}
public String getNameString() {
return nameString;
}
public void setNameString(String nameString) {
this.nameString = nameString;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Users [nameString=" + nameString + ", age=" + age + "]";
}
}
这里没有重写hashcode()方法
public class HashSetDemo {
public static void main(String[] args) {
//实例化Hashset对象
Set<String> set = new HashSet<String>();
//添加元素
set.add("a");
set.add("b1");
set.add("c");
set.add("c");
set.add("d");
for(String str:set) {
System.out.println(str);
}
//获取元素在set中没有索引,所以没有对应的get()方法,也不能用for(i)循环
System.out.println("----------------");
boolean flag = set.remove("b1");
System.out.println(flag);
for(String str:set) {
System.out.println(str);
}
System.out.println("----------------");
System.out.println(set.size());
System.out.println("*************************");
Set<Users> steSet = new HashSet<Users>();
Users u1 = new Users("lili", 18);
Users u2 = new Users("lili",18);
steSet.add(u1);
steSet.add(u2);
System.out.println(u1.hashCode());
System.out.println(u2.hashCode());
for(Users user:steSet) {
System.out.println(user);
}
}
}
输出结果:
在自定义的Users类中没有重写hashCode()方法,实例化内容相同的对象,输出两个结果且hashcode值不相同。
这里Users类里面重写hashcode()方法:
public class Users {
private String nameString;
private int age;
public Users() {
super();
// TODO Auto-generated constructor stub
}
public Users(String nameString, int age) {
super();
this.nameString = nameString;
this.age = age;
}
public String getNameString() {
return nameString;
}
public void setNameString(String nameString) {
this.nameString = nameString;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Users [nameString=" + nameString + ", age=" + age + "]";
}
//使用HashSet容器存储自定义对象,且不重复时,需要重写hashcode方法 和equals方法
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((nameString == null) ? 0 : nameString.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;
Users other = (Users) obj;
if (age != other.age)
return false;
if (nameString == null) {
if (other.nameString != null)
return false;
} else if (!nameString.equals(other.nameString))
return false;
return true;
}
}
输出的结果:
可以看出输出的结果两个对象的hashcode值相同,且只输出一个结果,( //使用HashSet容器存储自定义对象,且不重复时,需要重写hashcode方法 和equals方法)。
使用TreeSet:自定义一个Users类实现Comparable接口并实现compareTo方法,对对新进行排序
public class Users implements Comparable<Users> {
private String nameString;
private int age;
public Users() {
super();
// TODO Auto-generated constructor stub
}
public Users(String nameString, int age) {
super();
this.nameString = nameString;
this.age = age;
}
public String getNameString() {
return nameString;
}
public void setNameString(String nameString) {
this.nameString = nameString;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Users [nameString=" + nameString + ", age=" + age + "]";
}
//使用HashSet容器存储自定义对象,且不重复时,需要重写hashcode方法 和equals方法
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((nameString == null) ? 0 : nameString.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;
Users other = (Users) obj;
if (age != other.age)
return false;
if (nameString == null) {
if (other.nameString != null)
return false;
} else if (!nameString.equals(other.nameString))
return false;
return true;
}
@Override
//定义比较规则,按照年龄进行排序,如果年龄相同,按照名字排序
public int compareTo(Users o) {
System.out.println(this.age);
//System.out.println(o.age);
if(this.age > o.age) {
return 1;
}
if(this.age == o.age) {
//字符串类型,在String类中已经实现了compareTo方法
return this.nameString.compareTo(o.nameString);
}
return -1;
}
}
public class TreeSetDemo {
public static void main(String[] args) {
Set<String> set = new TreeSet<String>();
set.add("a");
set.add("d");
set.add("e");
set.add("a");
set.add("b");
set.add("c");
//TreeSet:不允许重复,有序排列
for(String string:set) {
System.out.println(string);
}
System.out.println("__________________");
Set<Users> treeSet = new TreeSet<Users>();
Users u1 = new Users("lili", 19);
Users u2 = new Users("ksfji",18);
Users u3 = new Users("yy",17);
treeSet.add(u1);
treeSet.add(u2);
treeSet.add(u3);
for(Users user:treeSet) {
System.out.println(user);
}
}
}
运行结果: