不管你是老师教的还是百度上查资料的,他们都是说set的集合是无序,不可重复的。但是在jdk1.7以上版本中有做一些改变,如果是数字的话会按照从小到大排序;如果是字符串的话会按照首字母排序。
查看Api会发现,set集合的功能与Collection集合的功能是一致的(就方法调用而言);
HashSet无序,不可重复,线程非同步。
哈希表底层使用的也是数组机制,数组中也存放对象,而这些对象往数组中存放时的位置比较特殊,当需要把这些对象给数组中存放时,那么会根据这些对象的特有数据结合相应的算法,计算出这个对象在数组中的位置,然后把这个对象存放在数组中。而这样的数组就称为哈希数组,即就是哈希表。
HashSet是通过元素的两个方法:hashCode与equals方法来完成;
TreeSet可以对set集合中元素进行排序
String实现了Comparable接口,所以可以直接进行排序
引用数据类型想要排序,必须实现Comparable接口
import java.util.HashSet;
import java.util.Iterator;
import sun.nio.cs.ext.TIS_620;
/**
* hashset本身具备去重复的功能?是滴
* 那么需要探究hashset为什么能够去重,它依靠的是什么?
*
* @author Administrator
*
*/
public class HashSetDemo {
public static void main(String[] args) {
//数据结构是哈希表,一个地址放两个东西
HashSet hs = new HashSet();
hs.add(new Person("liuting",18));
hs.add(new Person("xuyang",22));
hs.add(new Person("duanlian",32));
hs.add(new Person("wangwang",12));
hs.add(new Person("liuting",18));
Iterator it = hs.iterator();
while(it.hasNext()) {
System.out.println(it.next());//打印
}
}
}
class Person implements Comparable<Person> {
private String name;
private int sage;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSage() {
return sage;
}
public void setSage(int sage) {
this.sage = sage;
}
public Person() {
}
public Person(String name, int sage) {
super();
this.name = name;
this.sage = sage;
}
/**
* 返回值代表着容器中的具体位置的坐标
*/
@Override
public int hashCode() {//重写hashCode()方法
return this.getName().hashCode()+this.sage;
}
@Override
public boolean equals(Object obj) {
if(obj instanceof Person) {
Person p = (Person)obj;
// this.name 还没有存放进新集合
// p.getName()已经存放进去的
System.out.println(this.getName()+" "+p.getName());
return this.getName().equals(p.getName())&&this.getSage()==p.getSage();
}
return false;
}
@Override
public String toString() {//重写toString 方法
return "Person [name="+this.name+" ,age="+this.sage+"]";
}
/**
* 正数:后面的o比当前(this)大
*/
@Override
public int compareTo(Person o) {
int num = this.getSage() - o.getSage();
if (num==0) {
return this.getName().compareTo(o.getName());
}
return num ;
}
}
如果hashCode值相同,才会判断equals是否为true;
其他引用数据类型没有实现Comparable接口,那么会出现java.lang.ClassCastException: com.javaxl.Peroon cannot be cast to java.lang.Comparable,实现引用数据类型实现此接口就没问题了。
注意:对于判断元素是否存在,以及删除等操作,依赖的方法同样是hashCode、equals方法。
① List只依赖于equals方法
② Set依赖于hashCode、equals方法
③小李飞刀_集合框架
TreeSet是用来排序的,可以指定一个顺序,对象存入之后会按照指定的顺序排列
public class TreeSetDemo {
public static void main(String[] args) {
//数据结构是哈希表,一个地址放两个东西
TreeSet hs = new TreeSet();
hs.add(2);
hs.add(4);
hs.add(3);
hs.add(1);
hs.add(5);
Iterator it = hs.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
}
实体类需要实现 compareTo方法
@Override
public int compareTo(Person o) {
int num = this.getSage() - o.getSage();
if (num==0) {
return this.getName().compareTo(o.getName());
}
return num ;
}
运行结果:12345
当元素自身不具备比较性时,或者具备的比较性不是所需要的;注意:这时需要让集合自身具备比较性
定义一个类,实现comparator接口,实现compare方法
package dome.zking.collection.set;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.TreeSet;
/**
* Comparable接口的用途?
* 使添加的元素自身具备排序规则,这种排序规则又被称为自然排序
*
* 案例:
* 给已知的集合进行排序
*
* 当给对象赋予自然排序规则的时候必须按照以下规则来
* 先判断主要条件,再判断次要条件
*
* 需求变了
* 前面的排序规则只适用于近一周的福利模块(先按年龄,再按姓氏)
* 系统中有另一个模块,需要对于用户中排序规则进行更改(先按姓氏,再按年龄)
*
*比较器comparator接口
* 作用:使得容器具有比较性
*
* @author Administrator
*
*/
public class TreeSetDemo {
public static void main(String[] args) {
//数据结构是哈希表,一个地址放两个东西
TreeSet hs = new TreeSet(new PersomCop());
hs.add(new Person("liuting",18));
hs.add(new Person("xuyang",22));
hs.add(new Person("duanlian",32));
hs.add(new Person("wangwang",12));
hs.add(new Person("duanfei",32));
Iterator it = hs.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
}
/**
* 定义一个比较person的比较器
* 规则:先按姓氏,再按年龄
*
* 先主要条件再次要条件:如果不按照这个规则来,那么会发生数据丢失
* @author Administrator
*
*/
class PersomCop implements Comparator<Person>{
@Override
public int compare(Person o1, Person o2) {
int num = o1.getName().compareTo(o2.getName());
if (num == 0) {
return o1.getSage() - o2.getSage();
}
return num ;
}
}
注意:先主要条件再次要条件:如果不按照这个规则来,那么会发生数据丢失
当两种排序都存在时,比较器排序优先级更高
因此比较器用的多一些,在实际开发中,很多时候,引用数据类型是否具有比较性,或者比较规则,可能不由开发人员自己决定,
那么开发人员想要对应的引用数据类型按照自己的排序方式进行排列,那么就需要实现comparator接口,实现compare方法
1、TreeSet 是二差树实现的,Treeset中的数据是自动排好序的,不允许放入null值。
2、HashSet 是哈希表实现的,HashSet中的数据是无序的,可以放入null,但只能放入一个null,两者中的值都不能重复,就如数据库中唯一约束。
3、HashSet要求放入的对象必须实现HashCode()方法,放入的对象,是以hashcode码作为标识的,而具有相同内容的 String对象,hashcode是一样,所以放入的内容不能重复。但是同一个类的对象可以放入不同的实例 。