---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------
Collection中除了List之外还有一个派系叫做Set
Set:元素是无序的(存入和取出的顺序不一定一致),元素不可以重复
想重复,找List
public interface Set extends Collection
查阅API发现,Set集合的功能和Collection是一致的
子类,常用,HashSet、TreeSet
HashSet:底层数据结构是哈希表
HashSet只有一种取出方法,迭代器Iterator
HashSet线程是非同步的
HashSet hs = new HashSet();
hs.add(“111”);//结果为true
hs.add(“111”);//结果为false
hashSet是如何保证元素的唯一性的呢?
是通过元素的两个方法,hashCode和equals来完成的
如果元素的hashCode 值相同,才会判断equals是否为true
如果元素的hashCode值不同,不会调用equals
哈希表先看哈希值
若是对象是否相同的判定不是哈希值,而是自定义的,需要重载hashCode()
注意:对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashCode和equals方法
hashCode()方法和equals()方法来自于Object类,在Object类中,equals比较的是内存地址,而hashCode返回的也是内存地址,如果两个对象比较的equals值为true,则表示hashCode值也相同。
如果需要自定义比较方式,复写了equals方法,则需要用相应的方式复写hashCode方法,否则是达不到效果的。
HashSet存储的时候,会自动调用hashCode和equals,判断要不要往集合中存
HashSet判断一个元素是否存在,以及删除一个元素的时候,也会先调用hashCode和equals来判断。
示例:
import java.util.*;
class Demo
{
public static void main(String [] args)
{
HashSet hs = new HashSet();
hs.add(new Person("aaa",13));
hs.add(new Person("bbb",14));
hs.add(new Person("ccc",15));
hs.add(new Person("bbb",14));
hs.add(new Person("aaa",13));
Iterator it = hs.iterator();
while (it.hasNext())
{
Person p = (Person)it.next();
System.out.println("name:"+p.name+"---age:"+p.age);
}
}
}
class Person
{
String name;
int age;
Person(String name,int age)
{
this.name = name;
this.age = age;
}
public boolean equals(Object obj)
{
if (!(obj instanceof Person))
return false;
Person p = (Person)obj;
return this.name==p.name&&this.age==p.age;
}
public int hashCode()
{
return this.name.hashCode()+age*37;
}
}
TreeSet:底层数据结构是二叉树,可以对Set集合中的元素进行排序
要保证元素唯一性的依据:compareTo方法,返回0表示相等
TreeSet对元素的排序有两种,一种是自然排序,一种是客户化排序。
自然排序:
让元素自身具备比较性,元素需要实现Comparable接口,覆盖compareTo方法,这种方式也成为元素的自然顺序,或者叫默认顺序
Java类库中有一些类默认实现了Comparable接口,具有比较性
BigDecimal、BigInteger、Byte、Double、Float、Integer、Long、Short
Character
String
自定义的类想要具有比较性,就要手动的实现Comparable接口,复写compareTo方法。
TreeSet比较两个对象的大小,只看compareTo的值。
注意:排序时,当主要条件相同时,一定要判断一下次要条件。否则视为相同的元素。
Comparable接口,实现该接口可以强制让自定义的类的对象具有比较性
TreeSet的第二种排序方式:
当元素自身不具备比较性,或者具备的比较性不是所需要的,这时就需要让集合自身具备比较性。在集合初始化时,就有了比较方式。
定义比较器,将比较器对象作为参数传递给TreeSet集合的构造函数
TreeSet有一个构造函数
TreeSet(Comparator<? super E>comparator)
比较器:定义一个类实现Comparator接口,覆盖compara方法
当两种排序都在时,以比较器为主
示例:
import java.util.*;
class Demo
{
public static void main(String [] args)
{
TreeSet ts1 = new TreeSet();
ts1.add(new Person("rgv",16));
ts1.add(new Person("hth",23));
ts1.add(new Person("adfe",12));
ts1.add(new Person("dfe",12));
ts1.add(new Person("rgesg",4));
Iterator it1 = ts1.iterator();
while (it1.hasNext())
{
Person p = (Person)it1.next();
System.out.println("name:"+p.name+"---age:"+p.age);
}
TreeSet ts2 = new TreeSet(new MyComparator());
ts2.add(new Person("rgv",16));
ts2.add(new Person("hth",23));
ts2.add(new Person("adfe",12));
ts2.add(new Person("dfe",12));
ts2.add(new Person("rgesg",4));
Iterator it2 = ts2.iterator();
while (it2.hasNext())
{
Person p = (Person)it2.next();
System.out.println("name:"+p.name+"-------age:"+p.age);
}
}
}
//定义一个Person类,实现Comparable接口,让它具有比较性
//比较规则:姓名年龄都相同,视为对象相同
//排序规则:按年龄排序,年龄相同,按姓名字符串排序
class Person implements Comparable
{
String name;
int age;
Person(String name,int age)
{
this.name = name;
this.age = age;
}
public int compareTo(Object o)
{
Person p = (Person)o;
if (this.age>p.age)
return 1;
else if (this.age == p.age)
return this.name.compareTo(p.name);
else return -1;
}
}
//定义比较器,按姓名字符串排序
class MyComparator implements Comparator
{
public int compare(Object obj1,Object obj2)
{
Person p1 = (Person)obj1;
Person p2 = (Person)obj2;
return p1.name.compareTo(p2.name);
}
}
---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------