Set中的元素是无序的,所以不能存在重复元素
Set集合的功能和Collection是一致的,没有特有方法
HashSet
底层数据结构是哈希表。是线程不安全的,不同步。
HashSet是如何保证元素唯一性的呢?
是通过元素的两个方法,hashCode和equals来完成。
如果元素的HashCode值相同,才会判断equals是否为true。
如果元素的hashcode值不同,不会调用equals。
对于判断元素是否存在,以及删除等操作,依赖的方法是也是元素的hashCode和equals方法,方法同上
存储自定义对象时,一般需要重写Object类的hashcode和equals方法
import java.util.*;
class Person
{
private String name;
private int age;
Person(String name,int age)
{
this.name=name;
this.age=age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
public int hashCode()
{
return name.hashCode()+age*2; //重写hashcode方法,*2是保证新的hashcode尽可能不会重复
}
public boolean equals(Object obj)
{
if(!(obj instanceof Person))
return false;
Person p = (Person)obj;
return this.name.equals(p.name) && this.age==p.age; //重写equals方法
}
}
public class Test {
public static void main(String[] args) {
HashSet hs = new HashSet();
hs.add(new Person("张三",19));
hs.add(new Person("李四",20));
hs.add(new Person("张三",19));
hs.add(new Person("李四",19));
Iterator it = hs.iterator();
while(it.hasNext())
{
Person p = (Person)it.next(); //向下转型
System.out.println(p.getName()+"-----"+p.getAge());
}
}
}
/*张三-----19
李四-----20
李四-----19*/
TreeSet
会对Set集合中的元素进行排序,底层数据结构是二叉树。
两种排序方式:
1. 自然排序:
让元素自身具备比较性,元素需要实现Comparable接口,覆盖compareTo方法。
import java.util.*;
class Person implements Comparable //该接口强制让Person具备比较性
{
private String name;
private int age;
Person(String name,int age)
{
this.name=name;
this.age=age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
public int compareTo(Object obj) //重写compareTo方法,默认按照ASCII码比较字符串
{
if(!(obj instanceof Person))
throw new RuntimeException("不是Person对象");
Person p = (Person)obj;
int num = this.age - p.age; //首先按照年龄排序
if(num==0)
{
return this.name.compareTo(p.name); //如果年龄相同,再按照姓名排序
}
return num;
}
}
public class Test {
public static void main(String[] args) {
TreeSet ts = new TreeSet();
ts.add(new Person("张三",19));
ts.add(new Person("李四",20));
ts.add(new Person("张三",19));
ts.add(new Person("李四",19));
Iterator it = ts.iterator();
while(it.hasNext())
{
Person p = (Person)it.next(); //向下转型
System.out.println(p.getName()+"-----"+p.getAge());
}
}
}
compareTo方法return 0,则新添加的元素等于当前正在比较的元素,不能添加到集合中。
compareTo方法return 1,则新添加的元素大于当前正在比较的元素,添加到二叉树的右子树上
compareTo方法return -1,则新添加的元素小于当前正在比较的元素,添加到二叉树的左子树上
2. 比较器排序
当元素自身不具备比较性时,或者具备的比较性不是所需要的,这时就需要让集合自身具备比较性。
实现方法:实现一个单独的类作为比较器,将比较器对象作为参数传递给TreeSet集合的构造函数
import java.util.*;
class Person
{
private String name;
private int age;
Person(String name,int age)
{
this.name=name;
this.age=age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}
class MyCompare implements Comparator //实现Comparator接口
{
public int compare(Object o1,Object o2) //注意重写的是compare方法
{
Person p1 = (Person)o1;
Person p2 = (Person)o2;
int num = p1.getName().compareTo(p2.getName()); //首先按照年龄排序
if(num==0)
{
return p1.getAge()-p2.getAge(); //如果姓名相同,再按照年龄排序
}
return num;
}
}
public class Test {
public static void main(String[] args) {
TreeSet ts = new TreeSet(new MyCompare()); //比较器对象作为参数传递给构造函数
ts.add(new Person("张三",19));
ts.add(new Person("李四",20));
ts.add(new Person("张三",19));
ts.add(new Person("李四",19));
Iterator it = ts.iterator();
while(it.hasNext())
{
Person p = (Person)it.next(); //向下转型
System.out.println(p.getName()+"-----"+p.getAge());
}
}
}