set接口

1.set接口

  set接口是一个无序的、唯一的容器(排列顺序与添加的顺序无关)

  set接口提供的方法

public static void main(String[] args) {
		/**
		 * 增:add/addAll
		 * 删:clear/remove/removeAll/retainAll
		 * 改:
		 * 查:contains/containsAll
		 * 遍历:iterator
		 * 其他:size/isEmpty
		 */
		
		Set<Integer> set = new HashSet<Integer>();
		// [1]添加
		// 无序
		set.add(10);
		set.add(3);
		set.add(20);
		set.add(0);
		// 不能添加重复元素
		boolean r = set.add(1);
		System.out.println(set);
		
		// 【2】删除
//		set.remove(1);
//		set.clear();
//		System.out.println(set);
		
		// 【3】查看是否包含
		System.out.println(set.contains(1));
		
		// 【4】其他
		System.out.println(set.size());
		System.out.println(set.isEmpty());
	}

  

  set接口的遍历方法

public static void main(String[] args) {
		
		Set<String> set = new HashSet<String>();
		set.add("banana");
		set.add("apple");
		set.add("coco");
		
		// 快速遍历
		for (String item : set) {
			System.out.println(item);
		}
		
		// 迭代器
		Iterator<String> it = set.iterator();
		while(it.hasNext()) {
			String item = it.next();
			System.out.println(item);
		}
	}

 

  set接口的实现类常用的有HashSet、LinkHashSet、TreeSet

 

1.1 HashSet

 

HashSetSet接口的实现类,底层数据结构是哈希表。

 

HashSet是线程不安全的(不保证同步)

 

1.1.1 哈希表工作原理

 

1.1.2 添加自定义对象

根据哈希表工作原理,请存储一个自定义对象到HashSet

public class Student {
	private String id;
	private String name;
	private int age;

	// …
	

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		result = prime * result + ((name == null) ? 0 : name.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;
		Student other = (Student) obj;
		if (age != other.age)
			return false;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";
	}

}

  

总结

[1]如果HashSet中存储元素时元素一定要实现hashCode方法和equals方法。

[2] 优点:添加、删除、查询效率高;缺点:无序

 

1.2 LinkedHashSet

 

LinkedHashSet是Set接口的实现底层数据结构哈希表+链表

 

哈希表用于散列元素;链表用于维持添加顺序。

 

 

 

如果要添加自定义对象元素,也需要重写hashCodeequals方法。

 

 

1.3 TreeSet

TreeSet 是Set接口的实现类,底层数据结构是二叉树。

TreeSet 存储的数据按照一定的规则存储。存储规则让数据表现自然序。

 

1.3.1 TreeSet工作原理

 

添加一个新元素t存储的步骤

[1] 如果集合无元素,t直接加入;如果集合有元素,t和根节点比较;

[2] 如果t小于根节点;把t放到根节点的左子树上;重复1-3步骤

[3] t大于根节点;把t放到根节点的右子树上;重复1-3步骤

 

输出时按照一定的规则:子树->根节点->右子树

 

根据TreeSet工作原理,向TreeSet添加自定义元素

向TreeSet中添加元素时,一定要提供比较策略否则会出现ClassCastException

 

比较策略分两种:内部比较器外部比较器

 

1.3.2 内部比较器

一个自定义对象实现Comparable并实现compareTo方法通过指定具体的比较策略此时称为内部比较器

public class Student implements Comparable<Student>{
	private String id;
	private String name;
	private int age;

	// 。。。

	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";
	}

	@Override
	public int compareTo(Student o) {
		if(this.getAge()<o.getAge()) {
			return -1;
		}else if(this.getAge() == o.getAge()) {
			return 0;
		}else {
			return 1;
		}
	}

}

  

比较策略几种情况

[1] 比较策略一般当前对象写在前面,比较对象也在后面,比较结果默认升序,

如果想要降序,改变两个比较对象的位置即可。

 

return  this.getAge() - o.getAge() ;

  

1.3.3 外部比较

实际开发过程不知道添加元素的源代码无权修改别人的代码此时可以使用外部比较器。

 

Comparator 位于java.util包中,定义了compare(o1,o2) 用于提供外部比较策略。

TreeSet接受一个指定比较策略的构造方法,这些比较策略的实现类必须实现Comparator

接口

 

需求:按照字符串的长度比较

public class Test01 {
	public static void main(String[] args) {
		
		LenComparator lenComparator = new LenComparator();
		TreeSet<String> set2 = new TreeSet<String>(lenComparator);
		
		set2.add("banana");
		set2.add("coco");
		set2.add("apple");
		
		set2.add("apple");
		System.out.println(set2);
		
	}
}

class LenComparator implements Comparator<String>{

	@Override
	public int compare(String o1, String o2) {
		return o1.length() - o2.length();
	}	
}

 

  

使用匿名内部类优化

 

 

public class Test02 {
	public static void main(String[] args) {
		
		TreeSet<String> set2 = new TreeSet<String>(new Comparator<String>() {

			@Override
			public int compare(String o1, String o2) {
				return o1.length() - o2.length();
			}
			
		});
		
		set2.add("banana");
		set2.add("coco");
		set2.add("apple");
		
		set2.add("apple");
		System.out.println(set2);
		
	}
}

  

 

 

posted @ 2019-05-05 23:43  麻烦关下灯  阅读(165)  评论(0编辑  收藏  举报