--Set:元素是无序(存入和取出的顺序不一定一致)的,元素不可以重复
--HashSet:底层数据结构是哈希表
--TreeSet:底层数据结构是二叉树。
Set集合的功能和Collection是一致的。
public class HashSet_08 { public static void main(String[] args) { Demo h1=new Demo(); Demo h2=new Demo(); sop(h1);//调用的hashCode()方法 sop(h2); HashSet hs=new HashSet(); hs.add("java01"); hs.add("java02"); hs.add("java03"); hs.add("java04"); hs.add("java02");//无允许重复,这个添加失败 sop(hs.add("java05")); //true,添加成功 sop(hs.add("java05")); //false,添加失败 Iterator it=hs.iterator(); while(it.hasNext()){ sop(it.next()); } } public static void sop(Object obj){ System.out.println(obj); } } class Demo{ public int hashCode(){ return 199; } }
往hashSet集合中存入自定义对象,姓名年龄相同者为同一个人,重复元素
--HashSet:底层数据结构是哈希表
HashSet是如何保证元素唯一性呢?
是通过元素的两个方法,hashCode()和equals()来完成的。
如果元素的HashCode值相同,才会判断equals是否为true。
如果元素的HashCode值不同,不会调用equals。
a1hashCode~~~~~~~~~~~
a2hashCode~~~~~~~~~~~
a3hashCode~~~~~~~~~~~
a2hashCode~~~~~~~~~~~
a2--equals--a2
a1...25
a2...26
a3...27
注意:对于判断元素是否存在以及删除等操作,依赖的方法是元素的hashCode()和equals()方法
public class HashSet_09 { public static void main(String[] args) { // TODO Auto-generated method stub HashSet hs=new HashSet(); hs.add(new Teacher("a1",25)); hs.add(new Teacher("a2",26)); hs.add(new Teacher("a3",27)); hs.add(new Teacher("a2",26)); /* sop(hs.contains(new Teacher("a1",25))); //true 先判断hashCode sop(hs.remove(new Teacher("a3",27))); //true */ Iterator it=hs.iterator(); while(it.hasNext()){ Teacher t=(Teacher) it.next(); sop(t.getName()+"..."+t.getAge()); } } public static void sop(Object obj){ System.out.println(obj); } } class Teacher{ private String name; private int age; Teacher(String name,int age){ this.name=name; this.age=age; } public String getName(){ return name; } public int getAge(){ return age; } public int hashCode(){ System.out.println(this.name+"hashCode~~~~~~~~~~~"); return this.name.hashCode()+this.age*39; //*39 保证哈希值唯一性 } public boolean equals(Object obj){ if(!(obj instanceof Teacher)){ return false; } Teacher t=(Teacher) obj; System.out.println(this.name+"--equals--"+t.name); return this.getName().equals(t.getName()) && this.getAge()==t.getAge(); } }
Set:无序,不可以重复元素。
--HashSet:数据结构是哈希表。线程是非同步的。
保证元素唯一性的原理:判断元素的hashCode值是否相同
如果相同,还会继续判断元素的equals方法,是否为true
--TreeSet:可以对Set集合中的元素进行排序。
保证元素唯一性的依据:compareTo方法return 0
TreeSet排序的第一种方式:让元素自身具备比较性,元素需要实现Comparable接口,覆盖compareTo方法
这种排序也称为元素的自然顺序,也叫默认顺序。
TreeSet排序的第二种方式:当元素自身不具备比较性时,或者具备的比较性不是所需要的,这是就需要让集合自身具备比较性。
在集合初始化时,就有了比较方式。
public class TreeSet_01 { public static void main(String[] args) { // TODO Auto-generated method stub TreeSet ts=new TreeSet(); ts.add("cba"); ts.add("abcd"); ts.add("aaa"); ts.add("bbb"); Iterator it=ts.iterator(); while(it.hasNext()){ sop(it.next()); } /* aaa abcd bbb cba */ } public static void sop(Object obj){ System.out.println(obj); } }
需求:往TreeSet集合中存储自定义对象学生。
想按照学生的年龄进行排序
往TreeSet集合中存入对象,对象必须具备比较性
记住:排序时,主要条件相同时,一定要判断次要条件
public class TreeSet_02 { public static void main(String[] args) { TreeSet ts=new TreeSet(); ts.add(new Student("lisa02",22)); ts.add(new Student("lisa007",20)); ts.add(new Student("lisa09",19)); ts.add(new Student("lisa08",19)); //ts.add(new Student("lisa01",40)); Iterator it=ts.iterator(); while(it.hasNext()){ Student st=(Student) it.next(); sop(st.getName()+"..."+st.getAge()); } } public static void sop(Object obj){ System.out.println(obj); } } class Student implements Comparable { //该接口强制让学生具备比较性 private String name; private int age; Student(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) { if(!(obj instanceof Student)){ throw new RuntimeException("不是 学生对象"); } Student st=(Student) obj; System.out.println(this.name+"...compareTo..."+st.name); if(this.age>st.age){ return 1; }else if(this.age == st.age){ //return 0; 名字不同, 年龄相同,返回0,被视为同一对象 return this.name.compareTo(st.name); }else{ return -1; } } }
当元素自身不具备比较性,或者具备的比较性不是所需的。这时需要让容器自身具备比较性。
定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。
当两种排序都存在时,以比较器为主。
定义一个类,实现Comparator接口,覆盖compare方法
public class Comparator_03 { public static void main(String[] args) { // TODO Auto-generated method stub TreeSet ts=new TreeSet(new MyCompare()); ts.add(new Teacher("lisa02",22)); ts.add(new Teacher("lisa007",20)); ts.add(new Teacher("lisa09",19)); ts.add(new Teacher("lisa08",19)); ts.add(new Teacher("lisa007",33)); //ts.add(new Student("lisa01",40)); Iterator it=ts.iterator(); while(it.hasNext()){ Teacher st=(Teacher) it.next(); sop(st.getName()+"..."+st.getAge()); } } public static void sop(Object obj){ System.out.println(obj); } } class MyCompare implements Comparator{ @Override public int compare(Object o1, Object o2) { Teacher t1=(Teacher) o1; Teacher t2=(Teacher) o2; int num=(t1.getName().compareTo(t2.getName())); if(num==0){ /*if(t1.getAge()>t2.getAge()){ return 1; }else if(t1.getAge()==t2.getAge()){ return 0; }else{ return -1; }*/ //两种方式等价,Integer本身具备比较方法 return new Integer(t1.getAge()).compareTo(new Integer(t2.getAge())); } return num; } } class Teacher implements Comparable{ private String name; private int age; Teacher(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) { if(!(obj instanceof Teacher)){ throw new RuntimeException("不是 学生对象"); } Teacher st=(Teacher) obj; if(this.age>st.age){ return 1; }else if(this.age == st.age){ return this.name.compareTo(st.name); }else{ return -1; } } }
练习:按照字符串长度排序
字符串本身具备比较性,但是它的比较方式不是所需要的,这是就只能只用比较器
public class Comparator_04 { public static void main(String[] args) { // TODO Auto-generated method stub TreeSet ts=new TreeSet(new StringComparator()); ts.add("abcd"); ts.add("cc"); ts.add("cba"); ts.add("aaa"); ts.add("z"); ts.add("hahaha"); Iterator it=ts.iterator(); while(it.hasNext()){ sop("字符串为:"+it.next()); } } public static void sop(Object obj){ System.out.println(obj); } } class StringComparator implements java.util.Comparator{ @Override public int compare(Object o1, Object o2) { String s1=(String) o1; String s2=(String) o2; if(s1.length()>s2.length()){ return 1; }else if(s1.length() == s2.length()){ return s1.compareTo(s2); }else{ return -1; } } }