Set 接口的实现类:HashSet,TreeSet

1. HashSet

此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。

此类为基本操作提供了稳定性能,这些基本操作包括 add、remove、contains 和 size,假定哈希函数将这些元素正确地分布在桶中。对此 set 进行迭代所需的时间与 HashSet 实例的大小(元素的数量)和底层 HashMap 实例(桶的数量)的“容量”的和成比例。因此,如果迭代性能很重要,则不要将初始容量设置得太高(或将加载因子设置得太低)。

定义:public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, Serializable

// HashSet 构造方法摘要 
HashSet() // 构造一个新的空 set,其底层 HashMap 实例的默认初始容量是 16,加载因子是 0.75。 
HashSet(Collection<? extends E> c) // 构造一个包含指定 collection 中的元素的新 set。 
HashSet(int initialCapacity) // 构造一个新的空 set,其底层 HashMap 实例具有指定的初始容量和默认的加载因子(0.75)。 
HashSet(int initialCapacity, float loadFactor) // 构造一个新的空 set,其底层 HashMap 实例具有指定的初始容量和指定的加载因子。 

2. TreeSet

基于 TreeMapNavigableSet 实现。使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。

此实现为基本操作(addremovecontains)提供受保证的 log(n) 时间开销。

注意,如果要正确实现 Set 接口,则 set 维护的顺序(无论是否提供了显式比较器)必须与 equals 一致。(关于与 equals 一致 的精确定义,请参阅 ComparableComparator。)这是因为 Set 接口是按照 equals 操作定义的,但 TreeSet 实例使用它的 compareTo(或 compare)方法对所有元素进行比较,因此从 set 的观点来看,此方法认为相等的两个元素就是相等的。即使 set 的顺序与 equals 不一致,其行为也 定义良好的;它只是违背了 Set 接口的常规协定。

定义:public class TreeSet<E> extends AbstractSet<E> implements NavigableSet<E>, Cloneable, Serializable

// TreeSet 构造方法摘要 
TreeSet() // 构造一个新的空 set,该 set 根据其元素的自然顺序进行排序。 
TreeSet(Collection<? extends E> c) // 构造一个包含指定 collection 元素的新 TreeSet,它按照其元素的自然顺序进行排序。 
TreeSet(Comparator<? super E> comparator) // 构造一个新的空 TreeSet,它根据指定比较器进行排序。 
TreeSet(SortedSet<E> s) // 构造一个与指定有序 set 具有相同映射关系和相同排序的新 TreeSet。 
// TreeSet 一些特有的方法
E ceiling(E e) // 返回此 set 中大于等于给定元素的最小元素;如果不存在这样的元素,则返回 null。 
E floor(E e) // 返回此 set 中小于等于给定元素的最大元素;如果不存在这样的元素,则返回 null。 

E first() // 返回此 set 中当前第一个(最低)元素。 
E last() // 返回此 set 中当前最后一个(最高)元素。 

E higher(E e) // 返回此 set 中严格大于给定元素的最小元素;如果不存在这样的元素,则返回 null。 
E lower(E e) // 返回此 set 中严格小于给定元素的最大元素;如果不存在这样的元素,则返回 null。 

E pollFirst() // 获取并移除第一个(最低)元素;如果此 set 为空,则返回 null。 
E pollLast() // 获取并移除最后一个(最高)元素;如果此 set 为空,则返回 null。 

3. 分析

Collection
	|--List
		|--ArrayList
		|--LinkedList
		|--Vector
	|--set
		|--HashSet
			1. 底层数据结构是哈希表
			2. HashSet实现不是同步的
			3. HashSet通过hashCode(),equals()这两个方法保证元素的唯一性
			4. 如果元素的hashCode值相同,则调用equals判断返回值是否为true
			5. 如果元素的hashCode值不同,不会再调用equals进行判断
			6. 对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashCode(),equals()方法
		|--TreeSet
			1. 底层数据结构是二叉树
			2. TreeSet 实现不是同步的
			3. TreeSet 保证元素惟一性的依据:CompareTo() 方法 return 0;
			4. TreeSet 删除元素,判断是否包含元素都是依赖于compareTo()方法
			5. 元素若想要存入TreeSet里面,要求元素有比较性。
			6. TreeSet 排序的第一种实现方式:让元素具有比较性。
				需要元素实现 Comparable 接口里面唯一的 compareTo() 方法,让类具有比较性。
				这种方式也称为元素的自然顺序,或者叫做默认顺序。
			7. TreeSet 排序的第二种实现方式:让集合具备比较性。
				当元素自身不具备比较性,或者所具备的比较性不是所需的。
				这时就需要让集合自身具备比较性,在初始化集合的时候,传入比较器。
			8. 当两种排序方式都存在时,以比较器为主。

 

附:TreeSet 两种排序方式的实现方式

/*
 * 第一种方式: 让类具有比较性的方式
 *     通过让对象实现 Comparable 接口的方式,赋予元素比较性,让 TreeSet 利用重写的 CompareTo() 进行比较排序
 */
class Book01 implements Comparable<Book01>{
	private String name;
	private int price;
	public Book01(String name, int price) {
		this.name = name;
		this.price = price;
	}
	// 实现Comparable接口, 重写compareTo()方法,让类具备比较性
	@Override
	public int compareTo(Book01 o) {
		int _tmp = new Integer(this.price).compareTo(new Integer(o.getPrice()));
		if (_tmp == 0) {
			return this.name.compareTo(o.getName());
		}else {
			return _tmp;
		}
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getPrice() {
		return price;
	}
	public void setPrice(int price) {
		this.price = price;
	}
}
public class ComparableDemo {
	public static void main(String[] args) {
		TreeSet<Book01> treeSet = new TreeSet<>();
		treeSet.add(new Book01("JAVA01", 28));
		treeSet.add(new Book01("JAVA02", 29));
		treeSet.add(new Book01("JAVA03", 30));
		treeSet.add(new Book01("JAVA01", 28));
		
		Iterator< Book01> iterator = treeSet.iterator();
		while (iterator.hasNext()) {
			Book01 book = (Book01) iterator.next();
			System.out.println(book.getName()+":::::"+book.getPrice());
		}
	}
}

 

/*
 * 第二种的方式: 让集合具备比较能力
 *     通过让 MyComparator 类实现 Comparator 接口,创建出自己的比较器类。
 *     在集合初始化的时候,将自定义的比较器的匿名对象当作参数传入,让集合具备比较功能。
 */
class Book02{
	private String name;
	private int price;
	public Book02(String name, int price) {
		this.name = name;
		this.price = price;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getPrice() {
		return price;
	}
	public void setPrice(int price) {
		this.price = price;
	}
}
class MyComparator implements Comparator<Book02> {    // 自定义的实现了比较器(Comparator)接口的类

	@Override
	public int compare(Book02 o1, Book02 o2) {    // 实现比较器的 compare() 方法
		int _tmp = new Integer(o1.getPrice()).compareTo(new Integer(o2.getPrice()));
		if (_tmp == 0) {
			return o1.getName().compareTo(o2.getName());
		}else {
			return _tmp;
		}
	}
}
public class ComparatorDemo{
	public static void main(String[] args) {
		TreeSet<Book02> treeSet = new TreeSet<>(new MyComparator());
		treeSet.add(new Book02("JAVA01", 28));
		treeSet.add(new Book02("JAVA02", 29));
		treeSet.add(new Book02("JAVA03", 30));
		treeSet.add(new Book02("JAVA01", 28));
		
		Iterator< Book02> iterator = treeSet.iterator();
		while (iterator.hasNext()) {
			Book02 book = (Book02) iterator.next();
			System.out.println(book.getName()+":::::"+book.getPrice());
		}
	}
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值