JAVA学习第三十七课(常用对象API)- 集合框架(五)— Set集合:TreeSet集合

一、LinkedHashSet集合

HashSet下有子类LinkedHashSet

API文档关于LinkedHashSet的解释:

具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现。此实现与 HashSet 的不同之外在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,即按照将元素插入到 set 中的顺序(插入顺序)进行迭代。注意,插入顺序 受在 set 中重新插入的 元素的影响。(如果在 s.contains(e) 返回 true 后立即调用 s.add(e),则元素 e 会被重新插入到 set s 中。)

此实现可以让客户免遭未指定的、由 HashSet 提供的通常杂乱无章的排序工作,而又不致引起与 TreeSet 关联的成本增加

import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;

public class Main 
{
	public static void main(String[] args) 
	{
		//HashSet hash = new HashSet();无序
		HashSet hash = new LinkedHashSet();
		hash.add("b");
		hash.add("a");
		hash.add("c");
		hash.add("d");
		Iterator it = hash.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}
	}
}

如上,用LinkedHashSet就能够实现有序存储,但是有没有序不重要,关键是保证唯一。


二、TreeSet集合


API文档解释:

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

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

注意,如果要正确实现 Set 接口,则 set 维护的顺序(无论是否提供了显式比较器)必须与 equals 一致

总结一句话就是,TreeSet集合可以对Set集合中的元素进行排序,速度快,且不同步

而TreeSet的储存方式,实际上根据二叉树(红黑树)的存储特点进行存储,左孩子小于父亲,右孩子大于父亲

import java.util.Iterator;
import java.util.TreeSet;

public class Main 
{
	public static void main(String[] args) 
	{
		TreeSet tree = new TreeSet();
		tree.add("ad");
		tree.add("abc");
		tree.add("dsa");
		tree.add("bcd");
		
		Iterator it = tree.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}
	}
}

按照字典序排序输出结果。


TreeSet判断元素唯一的方式,就是根据比较方法的返回结果是否是0,是,则表示相同,不存储,与HashCode、equals无关。

import java.util.Iterator;
import java.util.TreeSet;

public class Man /*extends Object*/ implements Comparable
{
	private String name;
	private int 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;
	}
	public Man() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Man(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	@Override
	public int compareTo(Object arg0) {//对象的自然排序
		// TODO Auto-generated method stub
		if(!(arg0 instanceof Man))
			throw new ClassCastException();
		
			Man man = (Man)arg0;
		int te = this.age - man.age;//先按年龄排,再姓名
		return te==0?this.name.compareTo(man.name):te;
	}
}

public class Main {
	public static void main(String[] args)
	{
		TreeSet tree = new TreeSet();
		
		tree.add(new Man("ad",11));
		tree.add(new Man("ac",12));
		tree.add(new Man("sf",14));
		tree.add(new Man("d",11));
		tree.add(new Man("ad",11));
		tree.add(new Man("ad",12));
		Iterator it = tree.iterator();
		while(it.hasNext())
		{
			Man man = (Man)it.next();
			System.out.println(man.getName()+"::"+man.getAge());
		}
	}
}

TreeSet对元素进行排序的方式一:

要让元素自身具备比较功能,就要实现Comparable接口,覆盖CompareTo方法


如果对象不具备自然排序,或具备自然排序但是其排序方式不是我们需要的

TreeSet对元素进行排序的方式二(开发常用):

让集合自身具备比较功能,构造一个比较器,复写compare方法,将该类对象作为参数传递给TreeSet的构造函数

比较器比较常用,因为它可以避免一些 对象自身不足

import java.util.Iterator;
import java.util.TreeSet;
import java.util.Comparator;

public class ComparatorRule implements Comparator {
//构造一个根据Man类的name进行排序的比较器
	@Override
	public int compare(Object arg0, Object arg1) {
		// TODO Auto-generated method stub
		Man man = (Man)arg0;
		Man man2 = (Man)arg1;
		int te = man.getName().compareTo(man2.getName());
		//return 1;有序,输出,改变了二叉树的储存特点
		return te==0?man.getAge()-man2.getAge():te;
	}
}
public class Man /*extends Object*/ implements Comparable
{
	private String name;
	private int 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;
	}
	public Man() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Man(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	@Override
	public int compareTo(Object arg0) {
		// TODO Auto-generated method stub
		if(!(arg0 instanceof Man))
			throw new ClassCastException();
		
			Man man = (Man)arg0;
		int te = this.age - man.age;
		return te==0?this.name.compareTo(man.name):te;
	}
}

三、练习:比较器的应用

对字符串进行长度排序


import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

class ComparatorLengh implements Comparator
{
	public int compare(Object arg0, Object arg1) {
		// TODO Auto-generated method stub
		String str0 = (String) arg0;
		String str1 = (String) arg1;
		int te = str0.length() - str1.length();
		
		return te==0?str0.compareTo(str1):te;
	}
	
}
public class Main 
{
	public static void main(String[] args) 
	{
		TreeSet tree = new TreeSet(new ComparatorLengh());
		tree.add("ad");
		tree.add("abssc");
		tree.add("dsafsd");
		tree.add("bcd");
		tree.add("b");
		
		Iterator it = tree.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}
	}
}

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。