0130 set接口

特点:不能存储重复元素,没有下标,无序存取(怎么存的不一定怎么取)

例:

public class Demo06 {
	public static void main(String[] args) {
		HashSet<String> set=new HashSet<String>();
		set.add("abc");
		set.add("abc");
		for(String s:set){
			System.out.println(s);
		}
	}
}

  运行结果为:

abc

set是一个接口,那我们就只能创建子类对象,就创建Hashset集合对象

HashSet集合的数据存储是存储在哈希表中,哈希表实际上数组和链表结构的结合。默认的数组长度为16,默认的加载因子为0.75,也就是说到数据存储到第16*0.75长度的时候,会自动再开辟一个长度为16的集合,那当然这个数组长度和加载因子也可以通过构造方法自定义指定,但最好使用默认的,比较科学。

图解:

 

 

 

HashSet集合的所有方法都是继承的collection接口中的方法,包括add等等,直接拿过来用就好

为什么不能存重复值

首先HashSet在调用add方法的时候,首先去调用你添加对象的类的Hashcode方法去计算hash值,再看集合中如果不存在这个hash值,那就存储这个对象,如果有这个hash值那就再调用equls方法去比较内容,如果内容不同,则存入,如果相同,则丢弃不存。

这个Hashcode方法,是根据他的算法返回一值。

例:打印一下这个hashcode的值

public class Demo07 {

	public static void main(String[] args) {
		System.out.println("abc".hashCode());
		System.out.println("abc".hashCode());
		System.out.println(new Person("a",10).hashCode());
		System.out.println(new Person("a",10).hashCode());
	}
}

  这里发现 前两个abc的hashcode值是一样的,后两个值不一样,是因为我们自定义Person类中没有重写Hashcode方法和equls方法,默认的调用的是object类中的这两个方法。前两个一样是因为string类中重写了这两个方法。

图解;abc的hash值的算法

 

 

 

利用这些特点,我们创建一个自定义类,记得重写方法

public class Person {

	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;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public Person() {
		super();
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		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;
		Person other = (Person) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	
}

  创建测试类测试

public class Demo06 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		HashSet<String> set=new HashSet<String>();
		set.add("abc");
		set.add("abc");
		for(String s:set){
			System.out.println(s);
		}
		HashSet<Person> set2=new HashSet<Person>();
		set2.add(new Person("a",10));
		set2.add(new Person("a",10));
		set2.add(new Person("b",9));
		for(Person d:set2){
			System.out.println(d.toString());
		}
	}

} 

  运行结果为

abc
Person [name=a, age=10]
Person [name=b, age=9]

图解:

 

 因为set接口是无序存取,也就是说怎么存的不一定怎么取得,那set接口有一个子类LinkedHashSet结合,就是有序取值,怎么存的就是怎么取

代码展示:

public class Demo08 {

	public static void main(String[] args) {
		LinkedHashSet<String> set=new LinkedHashSet<String>();
		set.add("b");
		set.add("a");
		for(String s:set){
			System.out.println(s);
		}
	}
}

  运行结果为:

b
a

posted @ 2021-01-30 15:26  公雪  阅读(119)  评论(0编辑  收藏  举报