set集合

Set集合

特点:无序,不重复。

遍历:foreach,迭代器

扩容:初始容量16,负载因子0.75,扩容增量1倍

HashSet:存储唯一元素允许为空,由HashMap支持,无序线程不安全

TreeSet:作用是提供有序的Set集合,自然排序或者根据提供的Comparator进行排序,基于TreeMap实现

在这里插入图片描述
在这里插入图片描述
选择junit4,可以让方法单个实现(before,test)

before执行每个方法前先执行

public class HashSetTest {

    public static void main(String[] args) {
        Set books = new HashSet();
        //分别向books集合中添加两个A对象、两个B对象、两个C对象
        books.add(new A());
        books.add(new A());
        books.add(new B());
        books.add(new B());
        books.add(new C());
        books.add(new C());

        for (Object obj : books){
            System.out.println(obj);
        }//类A的equals()方法总是返回true,但没有重写其hashCode()方法
class A{
    @Override
    public boolean equals(Object obj){
        return true;
    }
}

//类B的hashCoded()方法总是返回1,但没有重写其equals()方法
class B{
    @Override
    public int hashCode(){
        return 1;
    }
}

//类C的hashCode()方法总是返回2,且重写了其equals()方法
class C{
    @Override
    public int hashCode(){
        return 2;
    }

    @Override
    public boolean equals(Object obj) {
        return true;
    }
}


上面程序中向books集合中分别添加了两个A对象、两个B对象和两个C对象,其中C类重写了equals()方法总是返回true,hashCode()方法总是返回2,这将导致HashSet把两个C对象当成同一个对象。

当把一个对象放入HashSet中时,如果需要重写该对象对应类的equals()方法,则也应该重写其hashCode()方法。其规则是:如果两个对象通过equals()方法比较返回true,这两个对象的hashCode值也应该相同。

如果两个对象通过equals()方法比较返回true,但这两个对象的hashCode()方法返回不同的hashCode值时,这将导致HashSet会把这两个对象保存在Hash表的不同位置,从而使两个对象都可以添加成功,这就与Set集合的规则有些出入了。

如果两个对象的hashCode()方法返回的hashCode值相同,但它们通过equals()方法比较返回false时将更麻烦:因为两个对象的hashCode值相同,HashSet将试图把它们保存在同一个位置,但又不行(否则将只剩下一个对象),所以实际上会在这个位置用链式结构来保存多个对象;而HashSet访问元素时也是根据元素的hashCode值来快速定位的,如果HashSet中两个以上的元素具有相同的hashCode值,将会导致性能下降。

当从HashSet中访问元素时,HashSet先计算该元素的hashCode值(也就是调用该对象的hashCode()方法的返回值),然后直接到该hashCode值对应的位置去取出该元素,这就是HashSet速度很快的原因。

重写hashCode()方法的基本规则
在程序运行过程中,同一个对象多次调用hashCode()方法应该返回相同的值。
当两个对象通过equals()方法比较返回true时,这两个对象的hashCode()方法应返回相等的值。
对象中用作equals()方法比较标准的Field,都应该用来计算hashCode值。

TreeSet类
TreeSet是SortedSet接口的实现类,正如SortedSet名字所暗示的,TreeSet可以确保集合元素处于排序状态。与HashSet集合想比,TreeSet还提供了如下几个额外的方法。

//如果TreeSet采用了定制排序,则该方法返回定制排序所使用的Comparator
//如果TreeSet采用了自然排序,则返回null
	public Comparator<? super E> comparator() {
	    return m.comparator();
	}

//返回集合中的第一个元素
    public E first() {
        return m.firstKey();
    }

//返回集合中的最后一个元素
   public E last() {
        return m.lastKey();
    }

//返回集合中位于指定元素之前的元素
//即小于指定元素的最大元素,参考元素不需要是TreeSet集合里的元素
    public E lower(E e) {
        return m.lowerKey(e);
    }

//返回此Set的子集,由大于或等于fromElement的元素组成
    public SortedSet<E> tailSet(E fromElement) {
        return tailSet(fromElement, true);
    }

创建一个学生类并实现编比较器接口

public class Student implements Comparable<Student>{
	
	private Integer sid;	
	private String sname;
	private int age;
 
	public Student(Integer sid, String sname, int age) {
		super();
		this.sid = sid;
		this.sname = sname;
		this.age = age;
	}
 
	public Integer getSid() {
		return sid;
	}
 
	public void setSid(Integer sid) {
		this.sid = sid;
	}
 
	public String getSname() {
		return sname;
	}
 
	public void setSname(String sname) {
		this.sname = sname;
	}
 
	public int getAge() {
		return age;
	}
 
	public void setAge(int age) {
		this.age = age;
	}
 
}

需要在这个学生类中实现hashCode和equals方法

    /*
    *hashCode可以将学号名字努力转成唯一的数字,相对于身份证
    */
    @Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((sid == null) ? 0 : sid.hashCode());
		result = prime * result + ((sname == null) ? 0 : sname.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 (sid == null) {
			if (other.sid != null)
				return false;
		} else if (!sid.equals(other.sid))
			return false;
		if (sname == null) {
			if (other.sname != null)
				return false;
		} else if (!sname.equals(other.sname))
			return false;
		return true;//学号名字年龄都相等才是同一个学生
	}
 
	@Override
	public String toString() {
		return "Student [sid=" + sid + ", sname=" + sname + ", age=" + age + "]";
	}
    
    /**
	 * 实现Comparable<Student>接口后需要重写的方法
     * 根据年龄排序,年龄相同则比较学号,默认是升序
	 */
	@Override
	public int compareTo(Student o) {
		if(this.getAge()-o.getAge()==0) {
			return this.getSid()-o.getSid();
		}
		return this.getAge() - o.getAge();
	}

再使用ThreeSet

    @Test
	public void test04() {
		TreeSet<Student> stu = new TreeSet<>();
		
		stu.add(new Student(1,"zs", 18));
		stu.add(new Student(1,"zs", 18));
		stu.add(new Student(2,"ls", 19));
		stu.add(new Student(4,"lihao", 10));
		stu.add(new Student(7,"lihao", 18));
		stu.add(new Student(5,"zengfanyan", 20));
		stu.add(new Student(3,"we", 30));
				
		for(Student s: stu) {
			System.out.println(s);
		}
	}	

运行输出结果:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值