——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-
Set集合中的元素是无序的,不可重复的元素:
为了实现不可重复,所以存在集合中的元素必须要有验证自身是否和其他元素相同的方法,这要靠在类中实现equals、hashCode方法。
Set接口的实现类有HashSet、LinkedHashSet、TreeSet,其中HashSet为主要实现类。使用Set重点是在元素排序上。
常用方法
Set的常用方法都是在Collection中定义的。所以跟其他集合框架的使用是一样的。如add()这些。
Set的无序性
HashSet的无序行是指元素是底层存储的位置是无序的,而不是随机性。使用哈希算法来确定存储位置。
保证元素的唯一性
Set集合中的元素是不可重复的,当先Set中添加相同元素时,后添加的不能添加进去。依靠重写equals和hashCode方法来保证元素的唯一性。
向Set中添加对象时,先调用对象的hashCode方法,计算哈希值,此哈希值确定了对象的存储位置,如果此位置没有对象存储,就将此对象存储到这里,如果此位置已有对象,再通过equals比较两个对象是否相同,如果相同,对象就不能再添加进来。如果不相同,就都存储。但一般不这样做,要求hashCode()方法和equals()方法一致。
class Person_1
{
private String name;
private int age;
Person_1(String name,int age)
{
this.name = name;
this.age = age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
//重写hashCode
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
//重写equals
public boolean equals(Object obj)
{
if(!(obj instanceof Person_1)){
return false;
}
Person_1 p =(Person_1)obj;
return this.name.equals(p.name) && this.age == p.age;
}
}
HashSet
是Set的主要实现类,元素的存储位置是靠哈希值来确定的。
public static void main(String[] args) {
Set set = new HashSet();
set.add(123);
set.add(456);
set.add("ssf");
set.add("hyj");
set.add(null);
System.out.println(set);
打印结果:[null, ssf, 456, hyj, 123]
}
LinkedHashSet
通过一个链表来维护元素添加进去的顺序。
public static void main(String[] args) {
Set set = new LinkedHashSet();
set.add(123);
set.add(456);
set.add("ssf");
set.add("hyj");
set.add(null);
for(Object obj :set)
{
System.out.println(obj);
}
}
打印结果: 123
456
ssf
hyj
null
TreeSet
TreeSet中的元素必须是同一个类的实例。
public static void main(String[] args) {
Set set = new TreeSet();
set.add(123);
set.add("adb");
}
这样会出现异常。
TreeSet可以按照添加进元素中的对象指定的顺序遍历,String、包装类都具有默认的可比较性,因为它们继承了Comparable接口。
此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法。
public static void main(String[] args) {
Set set = new TreeSet();
set.add(123);
set.add(345);
set.add(567);
System.out.println(set);
}
打印结果:[123, 345, 567]
添加自定义对象
有两种排序方式,1.自然排序,2.定制排序
自然排序:添加自定义类的实例,类必须实现Comparable接口。实现自然排序。当向TreeSet中添加元素时,依据元素的compareTo方法,确定按照哪个属性进行排序。返回0,虽然是仅是这两个对象的两个属性相同而已,但程序认为两个对象相同,进而后一个对象不能添加进来。
class Demo2 implements Comparable { private String name; private int age; public Demo2(String name, int age) { this.name = name ; this.age = age; } public String toString() { return this.name+this.age; } public int compareTo(Object o) { if(o instanceof Demo2) { Demo2 p = (Demo2)o; int i = this.age.compareTo(p.age); if(i == 0) { return this.name.compareTo(p.name); } return i; } //根据字符串name来进行排序,从小到大排。 return 0; }
定制排序
创建一个实现了Comparator接口的类对象,Comparator接口有一个compare()方法,在此方法中实现按照哪些属性进行排序。定制排序比自然排序优先级别高。Comparator com = new Comparator() { @Override public int compare(Object o1, Object o2) { if(o1 instanceof Customer&& o2 instanceof Customer) { Customer c1 = (Customer)o1; Customer c2 = (Customer)o2; int i = c1.getId().compareTo(c2.getId()); if (i==0) { return c1.getName().compareTo(c2.getName()); } return i; } return 0; } };
在 TreeSet的构造函数中添加com参数。
Set set = new TreeSet(com); set.add(new Customer("AA",22)); set.add(new Customer("BB",23)); set.add(new Customer("CC",21)); set.add(new Customer("DD",22)); for(Object o : set) { System.out.println(o); } 打印结果: Customer [name=CC, id=21] Customer [name=AA, id=22] Customer [name=DD, id=22] Customer [name=BB, id=23]