Set:集:中的方法和Collection一致,只要注意它的子类对象即可。取出元素只能用迭代器。
HashSet
TreeSet
HashSet——底层数据结构是:哈希表,不保证顺序,是不同步的。
哈希表:根据元素的自身特点来确定应该存储到什么位置上。
位置怎么确定呢?哈希算法。
哈希表的由来:提高查询速度。
【哈希表如何保证所存储的元素的唯一性呢?】
当哈希表出现相同成为冲突,这时说明两个元素的位置相同,再次比较一次两个元素的内容。用equals来完成内容的比较。
如果equals返回的是true,视为同一个元素,不存。如果返回是false,视为不同元素,存储。
【哈希值和内存地址的区别】
哈希值是通过哈希算法算出来的存储位置,如果哈希值相同,再判断equals ,否则不存储;
内存地址:是内存中的实际地址。
【如何往哈希表中存储自定义对象?】
必须覆盖hashCode方法,和equals方法。
【当不知道这个对象到底存储到那个容器中去时,该怎么办呢?】
那就将hashCode , equals ,toString全都覆盖。即使不覆盖也会从Object中继承。
HashSetDemo.java
【TreeSet】
可以给Set集合中的元素进行指定方式排序,默认情况下使用的是自然顺序。
【什么是自然顺序】
TreeSet排序的方式一:自然排序
元素自身具备的比较性实现了Comparable接口的compareTo方法。
【练习】TreeSetDemo.java
package day0916; import java.util.Iterator; import java.util.TreeSet; public class TreeSetDemo { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub TreeSet ts = new TreeSet(); ts.add("xixi"); ts.add("jfkk"); ts.add("jdfiew"); ts.add("xnncixi"); ts.add("wejkllkxi"); ts.add("iiweu"); for(Iterator it =ts.iterator(); it.hasNext();){ System.out.println(it.next()); } } }
TreeSet排序的方式二:TreeSetTest.java 比较器排序
如果元素自身不具备比较性或具备的比较性(自然顺序)不是所需要的。这时候只能用第二种方式。
让容器自身具备比较性。容器一初始化,就具备了比较功能。因为容器是在对象构造时完成的。通过构造方法TreeSet(Comparator)在容器初始化时可以指定一个比较器。需要实现Comparator接口,覆盖compare方法即可。所以这种方式成为比较器排序。
【练习】——TreeSetTest.java
package cn.itcast.api.p1.set.demo; import java.util.Iterator; import java.util.TreeSet; import cn.itcast.api.p2.comparator.ComparatorByName; import cn.itcast.bean.Person; public class TreeSetDemo { /** * @param args */ public static void main(String[] args) { /* * TreeSet:可以给其中的元素进行指定方式排序,使用的自然顺序。 * 自然顺序:就是元素自身的具备的比较性实现了Comparable接口的compareTo方法 * * */ TreeSet ts = new TreeSet(new ComparatorByName());//按照比较器。 ts.add(new Person("lisi1",20)); ts.add(new Person("lisi7",28)); ts.add(new Person("lisi9",22)); ts.add(new Person("lisi3",21)); ts.add(new Person("lisi5",26)); Iterator it = ts.iterator(); //迭代器用于取出TreeSet集合中的元素 while(it.hasNext()){ System.out.println(it.next().toString()); } } } package cn.itcast.api.p2.comparator; import java.util.Comparator; import cn.itcast.bean.Person; /** * 定义了一个根据Person的Name进行比较的比较器。 * @author Administrator * */ public class ComparatorByName extends Object implements Comparator { @Override public int compare(Object o1, Object o2) { Person p1 = (Person)o1; Person p2 = (Person)o2; int temp = p1.getName().compareTo(p2.getName()); return temp==0?p1.getAge()-p2.getAge():temp; } }
package cn.itcast.bean; /* * 要想让Person对象具备比较大小的功能。 * 就需要对person对象进行功能的扩展。 * 让Person去实现Comparable接口。让Person具备自然顺序。 覆盖compareTo方法。 * */ public class Person implements Comparable { private String name; private int age; public Person() { super(); } public Person(String name, int age) { super(); this.name = name; this.age = age; } /** * 覆盖Object类中的hashCode方法。建立Person对象自己特点的哈希值算法。 */ public int hashCode(){ final int NUMBER = 27; return name.hashCode() + age*NUMBER;//*27是为了尽量保证哈希值唯一。 } /** * 覆盖Object类中的equals方法,建立Person对象。 * 判断是否相同的依据。 根据Person自身的特点来判断。 */ 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; } /** * @return the name */ public String getName() { return name; } /** * @param name the name to set */ public void setName(String name) { this.name = name; } /** * @return the age */ public int getAge() { return age; } /** * @param age the age to set */ public void setAge(int age) { this.age = age; } /* (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { return name+":"+age; } @Override public int compareTo(Object o) { /* * 按照Person对象的年龄进行排序。从小到大。 */ /* * 进行对象比较的时候,通常,先比较主要条件,如果主要条件相同,在比较次要条件。 * 如果想要按照人的年龄排序,如果年龄相同,在比较一次姓名。 */ //麻烦写法。 // Person p = (Person)o; // if(this.age>p.age) // return 1; // if(this.age==p.age) // return this.name.compareTo(p.name); // return -1; //技巧性写法。 Person p = (Person)o; int temp = this.age - p.age; return temp==0?this.name.compareTo(p.name):temp; } }
【进行对象比较时】
通常,先比较主要条件,如果主要条件相同,再比较次要条件。