java集合框架:HashSet<E>_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > java集合框架:HashSet<E>

java集合框架:HashSet<E>

 2015/4/1 22:49:30  xiao1zhao2  程序员俱乐部  我要评论(0)
  • 摘要:目录1.无序&&唯一2.真的唯一么?3.先入为主4.Set的其他实现类HashSet实现了Set接口,内部主要是通过HashMap实现的.1.无序&&唯一publicclassHashSetDemo1{publicstaticvoidmain(String[]args){HashSet<String>set=newHashSet<>();String[]str=newString[]{"collection","list","set"
  • 标签:has Hash Java

目录

1.无序&&唯一
2.真的唯一么?
3.先入为主
4.Set的其他实现类

?

HashSet实现了Set接口,内部主要是通过HashMap实现的.

?

1.无序&&唯一
class="java" name="code">public class HashSetDemo1 {

	public static void main(String[] args) {
		HashSet<String> set = new HashSet<>();
		String[] str = new String[] { "collection", "list", "set", "itaretor", "map", "set" };
		Collections.addAll(set, str);
		System.out.println(set);
	}
}

运行结果:[set, itaretor, collection, list, map]

可以看到,set的打印顺序与数组str不同,且重复"set"只能存储一次,那么HashSet是如何判断两个对象是否是同一个对象的呢?

?

2.真的唯一么?

在HashMap内部对于是否是同一个对象是这样判断的:

(p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))));

与三个条件有关:1st.判断hash;2nd.判断==;3rd.调用equals(),即如果(1st && (2nd || 3rd))满足true,则视为对象.可见HashSet内元素的唯一并非真正意义上的唯一,而是取决于如何定义hashCode()和equals()方法.下面依次进行验证.

1)判断hashCode()

public class HashSetDemo2 {

	public static void main(String[] args) {
		HashSet<Person> set = new HashSet<>();
		Person p1 = new Person("小明");
		Person p2 = new Person("小明");
		set.add(p1);
		set.add(p2);
		System.out.println(set.size());
	}
}

class Person {
	String name;

	public Person(String name) {
		this.name = name;
	}

	@Override
	public int hashCode() {
		int code = super.hashCode();
		System.out.println("hashCode被执行:" + code);
		return code;
	}
}

运行结果:
hashCode被执行:366712642
hashCode被执行:1829164700
2
由结果可知hashCode()方法被执行,由于hash值不同,p2可以添加到set中.注意:不要在添加元素之后尝试修改HashSet当中参与生成hash值的属性,否则hash值的改变会导致很多问题.

2)判断"=="

当hashCode相等时,会通过==判断两个对象是否是同一个对象,如果是同一个将不会再进行equals判断(短路||).

public class HashSetDemo2 {

	public static void main(String[] args) {
		HashSet<Person> set = new HashSet<>();
		Person p1 = new Person("小明");
		set.add(p1);
		set.add(p1);
		System.out.println(set.size());
	}
}

class Person {
	String name;

	public Person(String name) {
		this.name = name;
	}

	@Override
	public int hashCode() {
		System.out.println("hashCode被执行");
		return 1;
	}

	@Override
	public boolean equals(Object o) {
		System.out.println("equals被执行");
		return true;
	}
}

运行结果:
hashCode被执行
hashCode被执行
1
注意,此段代码中的equals()未被调用.

3)调用equals判断

当两个对象hashCode相等但又不是同一个对象,将调用equals方法再次进行判断:如果true则视为同一个对象,否则视为两个对象(hash值冲突).

public class HashSetDemo2 {

	public static void main(String[] args) {
		HashSet<Person> set = new HashSet<>();
		Person p1 = new Person("小明");
		Person p2 = new Person("小明");
		set.add(p1);
		set.add(p2);
		System.out.println(set.size());
	}
}

class Person {
	String name;

	public Person(String name) {
		this.name = name;
	}

	@Override
	public int hashCode() {
		System.out.println("hashCode被执行");
		return 1;
	}

	@Override
	public boolean equals(Object o) {
		System.out.println("equals被执行");
		return false;
	}
}

运行结果:
hashCode被执行
hashCode被执行
equals被执行
2
如果上面equals返回true,则打印出的set.size()为1.

?

3.先入为主

HashSet在添加元素时,如果认定了重复元素,HashSet将遵循先入为主的原则,直接舍弃新元素.例:

public class HashSetDemo3 {

	public static void main(String[] args) {
		HashSet<Person> set = new HashSet<>();
		Person p1 = new Person("小明");
		Person p2 = new Person("小红");
		set.add(p1);
		set.add(p2);
		System.out.println(set);
	}
}

class Person {
	String name;

	public Person(String name) {
		this.name = name;
	}

	@Override
	public int hashCode() {
		return 1;
	}

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

	@Override
	public String toString() {
		return name;
	}
}

运行结果:[小明]

?

4.Set的其他实现类

1)TreeSet
内部通过二叉树结构存储数据,排序存储,可在构造时自定义Comparator按指定规则存储.

发表评论
用户名: 匿名