package com.alpha.demo;
import java.util.HashSet;
import java.util.Set;
class Book {
private String title;
private double price;
public Book(String title, double price) {
this.title = title;
this.price = price;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
long temp;
temp = Double.doubleToLongBits(price);
result = prime * result + (int) (temp ^ (temp >>> 32));
result = prime * result + ((title == null) ? 0 : title.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Book other = (Book) obj;
if (Double.doubleToLongBits(price) != Double.doubleToLongBits(other.price))
return false;
if (title == null) {
if (other.title != null)
return false;
} else if (!title.equals(other.title))
return false;
return true;
}
@Override
public String toString() {
return "Book [title=" + title + ", price=" + price + "]\n";
}
}
public class TestDemo {
public static void main(String[] args) throws Exception {
Set<Book> all = new HashSet<Book>();
all.add(new Book("Java", 69.8));
all.add(new Book("Java", 69.8)); // 全部属性相同
all.add(new Book("JSP", 69.8)); // 部分属性相同
all.add(new Book("Oracle", 79.8)); // 全都不同
System.out.println(all);
}
}
以后在非排序的情况下,只要是判断重复元素依靠的永远都是hashCode()与equals()。
一些简单的源码解析
HashSet是不允许存在重复元素的,分析其源码,来观察其底层的实现原理:
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable
{
/**
* 内部维护着一个HashMap
*/
private transient HashMap<E,Object> map;
// map中key的默认值
private static final Object PRESENT = new Object();
/**
* HashSet的默认构造函数为内部维护的HashMap实例化
*/
public HashSet() {
map = new HashMap<>();
}
/**
* 添加时将PRESENT与要添加的元素作为map的key与value添加至维护的map中
*
* @param e element to be added to this set
* @return {@code true} if this set did not already contain the specified
* element
*/
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
}
public class TreeSet<E> extends AbstractSet<E>
implements NavigableSet<E>, Cloneable, java.io.Serializable
{
private transient NavigableMap<E,Object> m;
private static final Object PRESENT = new Object();
TreeSet(NavigableMap<E,Object> m) {
this.m = m;
}
public TreeSet() {
this(new TreeMap<>());
}
}