Java集合框架(Collections Framework)(6)

这里判断字符串对象是否重复的方法是先调用String的hashcode()进行判断,如果相同,再调用String的equals()方法。其中String的hashcode()方法在计算hash值时,是根据每个字符计算的,相同字符位置处的相同字符运算结果相同。

所以上面几个字符串对象中,前缀"abcd"子串部分的hash运算结果相同,最后一个字符决定了这些字符串对象是否相同。插入时有两个"abcd1",所以总共调用了一次String的equals()方法。

如果是存储自定义的对象,如Student对象,该对象定义方式如下:

class Student { String name; int age; Student(String name,int n) { this.name = name; this.age = n; } //override toString() public String toString() { return this.name + " " + this.age; } //override equals() public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof Student)) { return false; } Student stu = (Student)obj; return this.name.equals(stu.name) && this.age == age; } }

即使重写了equals(),插入属性相同的Student对象到HashSet中时,也会认为不重复的。

import java.util.*; public class TestHashSet { public static void main(String[] args) { Set s = new HashSet(); s.add(new Student("Malong1",21)); s.add(new Student("Malong1",21)); s.add(new Student("Malong1",21)); for (Iterator it = s.iterator();it.hasNext();) { Object obj = it.next(); System.out.println(obj); } } }

结果:

Malong1 21 Malong1 21 Malong1 21

这是因为HastSet集合的底层首先调用Student的hashcode()方法,而Student没有重写该方法,而是继承自Object,所以每个对象的hashcode()都不相同而直接插入到集合中。

因此,需要重写Student的hashcode()方法。以下是一种重写方法:

public int hashCode() { return this.name.hashCode() + age*31; //31可以是任意数,但不能是1或0。 }

如果不加上"age*31",那么name部分的hash值有可能是相同的,但这很可能不是同一Student对象,所以应该加上age属性作为计算hash值的一部分元素。但不能直接加age,因为这样会导致"new Student("lisi3",23)"和"new Student("lisi2",24)"的hashcode相同(3+23=2+24),因此需要为age做一些修改,例如乘一个非0和1的整数。

在Student中重写hashCode()后,再插入下面这些Student对象,就能相对精确地判断是否为同一个Student元素。

s.add(new Student("lisi1",21)); s.add(new Student("lisi1",21)); //此处将调用equals(),且最终判断为重复对象 s.add(new Student("lisi2",24)); s.add(new Student("lisi3",23)); //此处将调用equals() s.add(new Student("Gaoxiao1",23)); s.add(new Student("Gaoxiao2",21)); s.add(new Student("Gaoxiao3",22));

结果:

lisi1 21 Gaoxiao1 23 Gaoxiao3 22 lisi2 24 lisi3 23 Gaoxiao2 21 LinkedHashSet集合

链表顺序的HashSet集合,相比HashSet,只需多记录一个链表索引即可,这就使得它保证了存储顺序和插入顺序相同。实现方式除了new对象时和HashSet不一样,其他任何地方都是一样的。

import java.util.*; public class TestHashSet { public static void main(String[] args) { Set s = new LinkedHashSet(); s.add(new Student("lisi1",21)); s.add(new Student("lisi1",21)); s.add(new Student("lisi2",24)); s.add(new Student("lisi3",23)); s.add(new Student("Gaoxiao1",23)); s.add(new Student("Gaoxiao3",21)); s.add(new Student("Gaoxiao2",22)); for (Iterator it = s.iterator();it.hasNext();) { Object obj = it.next(); System.out.println(obj); } } }

结果:

lisi1 21 lisi2 24 lisi3 23 Gaoxiao1 23 Gaoxiao3 21 Gaoxiao2 22 TreeSet集合

TreeSet集合以二叉树数据结构存储元素。二叉树保证了元素之间是排过序且相互唯一的,因此实现TreeSet集合最核心的地方在于对象之间的比较。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/349b058e608364c69d6a7c8d05332c22.html