Java 容器(三) Set

Java 容器(三) Set

1.这篇说到Set的用法,它的实现类有:

1)HashSet:不重复

2)TreeSet:不重复+主动排序

3)LinkedHashSet:不重复+保持插入时候的顺序

2.下面是具体用法:

package roadArchitectWeb.Test;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;
class Student implements Comparable<Student>{
	private Integer id;
	private String name;
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Student(Integer id, String name) {
		super();
		this.id = id;
		this.name = name;
	}
	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + "]";
	}
	@Override
	public int hashCode() {
		return this.id;
	}
	@Override
	public boolean equals(Object obj) {
		if(obj instanceof Student){
			Student stu = (Student)obj;
			if(stu.name == this.name)
				return true;
		}
		return false;
	}
	@Override
	public int compareTo(Student o) {
		return this.id.compareTo(o.id);
	}
}
class StudentComparator implements Comparator<Student>{
	@Override
	public int compare(Student o1, Student o2) {
		return o2.getId().compareTo(o1.getId());
	}
}
public class Test4 {
	protected static Set<Student> hashSet = new HashSet<Student>();
	protected static Set<Student> treeSetComparable = new TreeSet<Student>();
	protected static Set<Student> treeSetComparator = new TreeSet<Student>(new StudentComparator());
	protected static Set<Student> linkedHashSet = new LinkedHashSet<Student>();
	public static void main(String[] args) {
		hashSet.add(new Student(3,"sun"));
		hashSet.add(new Student(1,"zhao"));
		hashSet.add(new Student(2,"qian"));
		System.out.println("hashSet:"+hashSet);
		
		/*
		 *这里使用Comparable
		 */
		treeSetComparable.add(new Student(3,"sun"));
		treeSetComparable.add(new Student(1,"zhao"));
		treeSetComparable.add(new Student(2,"qian"));
		System.out.println("treeSetComparable:"+treeSetComparable);
		
		/*这里使用Comparator
		 *在讲Arrays的时候已经用了Comparator
		 *如果在treeset中使用的话,就在new Treeset时候传递一个 Comparator的实现类作为参数即可。
		 */
		treeSetComparator.add(new Student(3,"sun"));
		treeSetComparator.add(new Student(1,"zhao"));
		treeSetComparator.add(new Student(2,"qian"));
		System.out.println("treeSetComparator:"+treeSetComparator);
		
		linkedHashSet.add(new Student(3,"sun"));
		linkedHashSet.add(new Student(1,"zhao"));
		linkedHashSet.add(new Student(2,"qian"));
		System.out.println("linkedHashSet:"+linkedHashSet);
	}
}


3.三种实现方式都要重写hashcode和equals,为什么?

1)当我们想让对象不重复的进行保存的时候,我们会想到保存到Set里面,这是为什么?

因为Set的实现类提供了对一个对象进行不重复判断的方法,他会根据这个方法来判断两个对象是否一样,这个方法是equals;

2)既然有了equals方法会什么还要重写?

因为每个人认为的相同的标准不一样,equals方法默认方法如下:

    public boolean equals(Object obj) {
        return (this == obj);
    }

它比较的是两个对象的地址是否一样,这样即使两个对象的内容完全一样,但是第二个是new的,也会认为不一样这个时候如果我想把这两个对象当成一样的来看(这是正常人想法),那么就要重写equals,给他一个新的标准,比如比较两个对象的内容即可,不比较地址:

public boolean equals(Object obj) {
		if(obj instanceof Student){
			Student stu = (Student)obj;
			if(stu.name == this.name && stu.id == this.id)
				return true;
		}
		return false;
	}

3)重写equals就可以了,为什么还要重写hashcode?

首先要了解hashcode是做什么的?   保存操作,当一个对象作为map的键的时候,Java怎么区分这个键,实际上它是通过键值来区分的,也就是说这个对象作为键,会自动产生一个键值,这个键值是怎么产生的?  就是通过hashcode

		HashMap<Student, String> map = new HashMap<Student,String>();
		Student student1 = new Student(1, "a");
		Student student2 = new Student(2, "a");
		Student student3 = new Student(3, "a");
		map.put(student1,"student1");
		map.put(student2,"student2");
		map.put(student3,"student3");

那为什么要重写hashcode,因为默认的hashcode也指的是对象的地址,这样的话如果如果new一个对象,即使值完全一样也是无法取出的,因为地址是新开辟的:

去掉Student中的hashcode方法,然后执行:

		HashMap<Student, String> map = new HashMap<Student,String>();
		Student student1 = new Student(1, "a");
		Student student2 = new Student(2, "a");
		Student student3 = new Student(3, "a");
		map.put(student1,"student1");
		map.put(student2,"student2");
		map.put(student3,"student3");
		Student student4 = new Student(2, "a");
		System.out.println("map:"+map.get(student4));

结果是:

map:null

怎么才能取出呢? 那就要改变hashcode生成方法,改变它的键值区分方式:

	@Override
	public int hashCode() {
		return this.id;
	}
再取出,就是:
map:student2

总的来说,使用map的时候,你不把这个对象作为键,就不可以不重写hashcode;但是Set是map实现的,它把对象作为键,那么用set的实现类的时候就要重写hashcode,以实现你想要的效果;

4.总结

1)Set和Map的实现类,其方式都是采用Map,所以都要重写hashcode方法;

2)继承Comparable接口的时候,说明有了排序方法,但只有在支持排序的集合里面才会主动排序,如treeSet,treeMap;Comparator也一样

3)List不支持插入的时候排序,所以list对Comparator和Comparable都支持是通过  Colections.sort,一个list参数代表Comparable排序,两个说明第二个参数是Comparator的实现类。Array同List.
4)linkedHashSet在迭代访问的时候更快,同时记录插入顺序;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值