技术问答-8 java中的集合(3)-Set

版权声明:本文为博主原创文章,未经博主允许不得转载,如需转载请在明显处标明出处! https://blog.csdn.net/qq_36291682/article/details/86677442

Set

一、set是什么

Set是一种没有重复元素的集合,它所有的方法都是直接继承Collection接口,并且添加了一个对重复元素的限制,Set要求强化了equals和hashCode两个方法,以使set集合可以对元素进行排序和对比。

二、方法

Set没有在Collection上新增接口 但是他的子类添加新方法了

返回值 方法 说明
SortedSet< E > subSet(E fromElement,E toElement) set的子集,从某个元素到某个元素
SortedSet< E > headSet(E toElement) 从第一个元素到指定元素(不包含)
SortedSet< E > tailSet(E fromElement) 从最后一个到指定元素(包含)
E first() 第一个元素
E last() 最后一个元素
三、NavigableSet

NavigableSet继承自SortedSet

返回类型 方法 描述
E lower(E e) 返回指定对象之前的元素,没有时返回null
E floor(E e) 返回小于或等于指定元素,没有时返回null
E higher(E e) 返回指定对象之后的元素,没有时返回null
E ceiling(E e) 返回大于或等于指定对象的元素,没有时返回null
NavigableSet< E> subSet(E,boolean,E,boolean) 返回指定端点之间的元素,布尔值决定是否包含指定元素
NavigableSet< E> headSet(E,boolean) 返回指定端点前元素组成的集合,布尔值决定是否包含指定元素
NavigableSet< E> tailSet<E,boolean> 返回指定端点后的元素,布尔值决定是否包含指定元素
NavigableSet< E> decendingSet() 返回与原集合相反排序的集合
E pollFirst() 移除并返回集合第一个元素,集合为空是返回null
E pollLast() 移除并返回集合最后一个元素,集合为空时返回null
三、通用实现

HashSet LinkedHashSet TreeSet
1. HashSet

  • 不能保证元素的排列顺序
  • 不是同步的
  • 集合元素可以是null,但只能有一个null (set本身是用map 实现的 )
  • 如果根据对象的指定属性去重的话只需要重写HashCode即可

2. TreeSet

  • TreeSet中存储的类型必须是一致的,不能一会儿存储int一会儿存储String
  • TreeSet是NavigableSet (NavigableSet 继承 SortSet)的接口的唯一实现类,TreeSet可以保证元素处于排序状态。
  • TreeSet支持2中排序方式,自然排序和定制排序,其中自然排序为默认排序方式
  • 自然排序
package along;

import java.util.TreeSet;

/**
 * 1.定义一个类 Stu 实现Compareble接口 2.重写Comparable接口中的compareTo方法
 * 3.在compareTo中根据age属性排序
 * 
 * @author Administrator
 *
 */
public class Stu implements Comparable<Stu> {
	public static void main(String[] args) throws Exception {
		TreeSet<Stu> sets = new TreeSet<>();
		Stu s = new Stu();
		s.setAge(18);
		Stu s2 = new Stu();
		s2.setAge(21);
		Stu s3 = new Stu();
		s2.setAge(18);
		sets.add(s);
		sets.add(s2);
		sets.add(s3);
		System.out.println(sets.size());
	}

	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 int compareTo(Stu o) {
		if (this.getAge() > o.getAge()) {
			return 1;
		} else if (this.getAge() == o.getAge()) {
			return 0;
		} else {
			return -1;
		}
	}

}

  • 定制排序
    当元素自身不具备比较条件时,或者具备的比较条件不是所需要的。这时就要让集合自身具备比较性,也就是不让对象自己个儿比较,由我们自己写一个对象的比较方法,在初始化时,就有了比较方法

    例子:Stu是用age比较大小的,在某些地方我要用其他属性比较大小

package along;
import java.util.Comparator;
import java.util.TreeSet;
public class javaTest {
	public static void main(String[] args) {
		TreeSet<Stu> sets = new TreeSet<Stu>(new MyCom());
		Stu s1 = new Stu();
		s1.setWork(1);
		Stu s2 = new Stu();
		s2.setWork(2);
		Stu s3 = new Stu();
		s3.setWork(2);
		sets.add(s1);
		sets.add(s2);
		sets.add(s3);
		System.out.println(sets.size());
	}
}
class MyCom implements Comparator<Stu>{
	public int compare(Stu o1, Stu o2) {
		if (o1.getWork() > o2.getWork()) {
			return 1;
		} else if (o1.getWork() == o2.getWork()) {
			return 0;
		} else {
			return -1;
		}
	}
}
package along;
import java.util.TreeSet;
/**
 * @author Administrator
 */
public class Stu implements Comparable<Stu> {
	private String name;
	private int age;
	//工作年限
	private float work;
	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 float getWork() {
		return work;
	}

	public void setWork(float work) {
		this.work = work;
	}

	// 重写
	public int compareTo(Stu o) {
		if (this.getAge() > o.getAge()) {
			return 1;
		} else if (this.getAge() == o.getAge()) {
			return 0;
		} else {
			return -1;
		}
	}
}

3. LinkedHashSet

  • LinkedHashSet集合也是使用hashCode值来决定元素存储位置的,
  • 但是它同时使用链表维护元素的次序。这样使得元素看起来像是以插入顺序保存的 ,
  • 它重写了父类的afterNodeAccess,这个方法里边维护了一个双向链表 ,
  • LinkedHashMap 顺序有2种方式,默认是按照插入顺序进行排序的,也可以按照访问顺序进行排序,如果我们制定按照访问顺序进行排序(accessOrder = true ),那么我们在get()操作后,会将这次访问的元素移到链表尾部,不断访问可以形成按照访问顺序排序的链表。
  • 我们可以重写removeEldestEntry方法返回true,可以指定插入元素时移除最老的元素。

4. 专用实现

  • EnumSet
package along;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Set;
public class javaTest {
	public static void main(String[] args) {
		//集合元素就是EnumDemo中的所有枚举值
		EnumSet<EnumDemo> es = EnumSet.allOf(EnumDemo.class);
		System.out.println(es);
		
		//创建一个空集合 集合类型是EnumDemo
		EnumSet<EnumDemo> es1 = EnumSet.noneOf(EnumDemo.class);
		System.out.println(es1);
		es1.add(EnumDemo.ONE);
		es1.add(EnumDemo.TWO);
		System.out.println(es1);
		
		//以指定枚举创建集合
		EnumSet<EnumDemo> es2 = EnumSet.of(EnumDemo.ONE, EnumDemo.TWO);
		System.out.println(es2);
		
		//两个枚举范围内的所有枚举
		EnumSet<EnumDemo> es3 = EnumSet.range(EnumDemo.ONE, EnumDemo.THREE);
		System.out.println(es3);
		
		//es4 = 枚举全部值  - es3包含的枚举值
	    EnumSet<EnumDemo> es4 = EnumSet.complementOf(es3);
        System.out.println(es4);
		
        //复制Collection 集合中的所有元素来创建EnumSet集合
        Set  c = new HashSet<>();
        c.add(EnumDemo.ONE);
        EnumSet<EnumDemo> es5 = EnumSet.copyOf(c);
        System.out.println(es5);
        
        //添加非枚举类型后 会报错
        c.add("TWO");
        es5 = EnumSet.copyOf(c);
        //java.lang.String cannot be cast to java.lang.Enum
	}
}
  • CopyOnWriteArraySet
    底层实现原理是数组,上层实现原理是CopyOnWriteArrayList
    不可存放重复元素,是线程安全的(lock)
    小知识点:
//List去重 
List<Stu> list = new ArrayList<Stu>();
List<Stu> listUniq = new ArrayList<Stu>(new HashSet<Stu>(list));

猜你喜欢

转载自blog.csdn.net/qq_36291682/article/details/86677442