Set接口中的方法和Collection一致
HashSet hs = new HashSet();
hs.add("hehe");
hs.add("haha");
hs.add("heihei");
hs.add("lala");
Iterator it = hs.iterator();
while(it.hasNext()) {
System.out.println(it.next()); //无序
}
自身的hashCode方法算出了hash值,从而来决定在哈希表中位置,可以覆盖,所以无序
//HashSet数据结构是哈希表,所以存储元素的时候使用元素的hashCode方法来确定位置,如果位置相同,再通过
//元素的equals来确定内容是否相同
HashSet hs = new HashSet();
hs.add(new Person("list1",21));
hs.add(new Person("list2",22));
hs.add(new Person("list3",23));
hs.add(new Person("list4",24));
hs.add(new Person("list1",21));
Iterator it = hs.iterator();
while(it.hasNext()) {
Person p = (Person)it.next();
System.out.println(p.getName()+"--"+p.getAge());
}
//Person
public class Person extends Object {
private String name;
private int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//覆盖hashCode和equals方法
@Override
public boolean equals(Object obj) {
if(this == obj) {
return true;
}
if(!(obj instanceof Person)) {
throw new ClassCastException("类型错误!");
}
System.out.println(this+"..equals.."+obj);
Person p = (Person)obj;
return this.name.equals(p.name) && this.age == p.age;
}
@Override
public int hashCode() {
System.out.println(name+"|"+age+"...hashCode=" + (name.hashCode()+age*35));
return name.hashCode()+age*35;
}
}
HashSet hashSet = new HashSet();
hashSet.add(new Person("zhangsan", 12));
hashSet.add(new Person("lisi", 12));
hashSet.add(new Person("zhangsan", 12)); //如果不重写hascode和equals,这会看作是不同对象
System.out.println(hashSet); //[Person [name=zhangsan, age=12], Person [name=zhangsan, age=12], Person [name=lisi, age=12]]
}
从顶部注释来看,我们就可以归纳HashSet的要点了:
我们知道Map是一个映射,有key有value,既然HashSet底层用的是HashMap,那么value在哪里呢???
可以很明显地看到,Set集合的底层就是Map,所以我都没有做太多的分析在上面,也没什么好分析的了。
HashSet源码分析
public class TestHashSet {
/***
* HashSet底层源码分析
* private transient HashMap<E,Object> map;
* private static final Object PRESENT = new Object();
* public HashSet() {
map = new HashMap<>();//创建HashSet时,底层创建的是一个HashMap对象
}
public boolean add(E e) {
key-->e ,value-->PRESENT ,是一个Object类型的对象
map集合中的所有value都是统一的Object类型对象
return map.put(e, PRESENT)==null;
}
public int size() {
return map.size();
}
public boolean contains(Object o) {
return map.containsKey(o); //在map集合中判断key是否存在
}
public Iterator<E> iterator() {
//获取map集合中所有的key的集合,再得到迭代器对象
return map.keySet().iterator();
}
HashSet使用了HashMap的数据结构,
底层都是哈希表 (顺序表+链表)
* @param args
*/
public static void main(String[] args) {
//HashSet底层数组结构使用的是hash表 ,主结构数组, +链表
//创建集合对象
HashSet hs=new HashSet();
hs.add("hello");
hs.add("world");
hs.add("java");
System.out.println(hs.add("world"));
System.out.println("集合中元素的个数:"+hs.size());
System.out.println(hs);
System.out.println(hs.contains("java")+"\t"+hs.contains("sql"));
//使用迭代器遍历元素
Iterator ite=hs.iterator();
while(ite.hasNext()){
System.out.println(ite.next());
}
}
}
有序的HashSet
HashSet hs = new LinkedHashSet();
hs.add("hehe");
hs.add("haha");
hs.add("heihei");
hs.add("lala");
Iterator it = hs.iterator();
while(it.hasNext()) {
System.out.println(it.next()); //无序
}
1. 让元素自身具备比较功能,需要实现Comparable接口,覆盖compareTo方法 TreeSet就是利用元素的比较方法来排序和排重
//Main
//以年龄排序
TreeSet ts = new TreeSet();
ts.add(new Person("zhangsan",28));
ts.add(new Person("zhangsan1",26));
ts.add(new Person("zhangsan2",22));
ts.add(new Person("zhangsan3",35));
ts.add(new Person("zhangsan3",28));
Iterator it = ts.iterator();
while(it.hasNext()) {
Person p = (Person)it.next();
System.out.println(p.getName()+"--"+p.getAge());
}
//zhangsan2--22
//zhangsan1--26
//zhangsan--28
//zhangsan3--28
//zhangsan3--35
//Person
public class Person extends Object implements Comparable {
private String name;
private int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//覆盖hashCode和equals方法
@Override
public boolean equals(Object obj) {
if(this == obj) {
return true;
}
if(!(obj instanceof Person)) {
throw new ClassCastException("类型错误!");
}
System.out.println(this+"..equals.."+obj);
Person p = (Person)obj;
return this.name.equals(p.name) && this.age == p.age;
}
@Override
public int hashCode() {
System.out.println(name+"|"+age+"...hashCode=" + (name.hashCode()+age*35));
return name.hashCode()+age*35;
}
@Override
public int compareTo(Object o) {
Person p =(Person)o;
int temp = this.age-p.age;
return temp==0?this.name.compareTo(p.name):temp;
// if(this.age>p.age) {
// return 1;
// }
// if(this.age<p.age) {
// return -1;
// }
// if(this.age==p.age) {
// this.name.compareTo(p.name);
// }
}
}
2. 有的时候元素自身不能具备比较,可以让集合自身具备比较器
让集合自身具备比较功能,定义一个类实现Comparator接口,覆盖Compare方法,
将该类对象作为参数传递给TreeSet构造函数
//main
TreeSet ts = new TreeSet(new ComparatorByName());
ts.add(new Person("zhangsan",28));
ts.add(new Person("zhangsan1",26));
ts.add(new Person("zhangsan2",22));
ts.add(new Person("zhangsan3",35));
ts.add(new Person("zhangsan3",28));
Iterator it = ts.iterator();
while(it.hasNext()) {
Person p = (Person)it.next();
System.out.println(p.getName()+"--"+p.getAge());
}
//ComparatorByName
public class ComparatorByName 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;
}
}
比较器固定返回1 return 1
,可以实现有序TreeSet集合,放入和取出一样
字符串按长度排序
//main
TreeSet ts = new TreeSet(new ComparatorByLength());
ts.add("asfsa");
ts.add("asfsasadfadsgf");
ts.add("asfs14gsdaa");
ts.add("asfsas");
Iterator it = ts.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
//ComparatorByLength
public class ComparatorByLength implements Comparator {
@Override
public int compare(Object o1, Object o2) {
String s1 = (String)o1;
String s2 = (String)o2;
int temp = s1.length()-s2.length();
return temp==0?s1.compareTo(s2) : temp;
}
}
TreeSet源码分析
/**
* TreeSet的底层所使用的是TreeMap -->红黑树
* TreeSet JDK源码分析
* private transient NavigableMap<E,Object> m; //一个接口,间接继承了Map
* private static final Object PRESENT = new Object();
* public TreeSet() {
this(new TreeMap<E,Object>()); //创建了一个TreeMap的对象
}
//调用的本类中的带参构造方法
TreeSet(NavigableMap<E,Object> m) {
this.m = m; //接口new 实现类
}
public TreeSet(Comparator<? super E> comparator) {
this(new TreeMap<>(comparator)); //调用了本类中的带参构造方法
}
添加方法
public boolean add(E e) {
return m.put(e, PRESENT)==null; //传入的元素作为Map中的key,统一的值为Object类型的对象
}
public int size() {
return m.size();
}
* @author Administrator
*
*/
public class TestTreeSet {
public static void main(String[] args) {
//创建集合对象
//TreeSet ts=new TreeSet();
//Comparator comc=new ComCharactor();//创建外部比较器对象
Comparator com=new ComCharactorAndAge();
TreeSet ts=new TreeSet(com);
//创建Person对象
Person p1=new Person("marry", 20);
Person p2=new Person("lili", 19);
Person p3=new Person("jack", 20);
Person p4=new Person("marry", 18);
//添加到集合中
ts.add(p1);
ts.add(p2);
ts.add(p3);
ts.add(p4);
System.out.println("集合中元素的个数:"+ts.size());
System.out.println(ts);
}
}