Set集合
Set不重复集。无序。
Set不能通过下标获取指定的元素。因为无序所以没有下标。可以使用Iterator的方式迭代集合。
若我们把List看成是有许多格子的盒子,那么Set就好像一个袋子。
hashCode()方法:
hashCode()方法是Object定义的方法。所以每个类都会有该方法。
若我们定义的类重写了equals()方法,就要重写hashCode()方法。
若equals方法返回true,那么这两个对象应该有相同的hashCode值。
反过来不是必须的,但最好是这样。可以提高诸如HashSet这样的数据结构的效率。
eclipse 右键空白处,source,Generate Constructor using Fields自动生成构造方法,不勾选参数,则生成无参构造方法。
source ,Generate Getters and Setter得到get和set方法。
source, Generate hashCode() and equals()生成hashCode()算法并且重写equals方法。
package day04;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* Set集合 无序且不重复集
* 常用实现类:
* HashSet:使用散列算法实现的Set集合 哈希
*
*/
public class DemoSet {
public static void main(String[] args) {
/**
* 实例化一个HashSet集合
*/
Set set = new HashSet();
/**
* 向集合添加元素也使用add
* 但是add方法不是向集合末尾追加元素,因为无序
*/
set.add("One");
set.add("Two");
set.add("Three");
/**
* Set集合没有get(int index)方法
* 我们不能像使用List那样,根据下标获取元素。
* 像获取元素需要使用Iterator
*/
Iterator it = set.iterator();
while(it.hasNext()){
String element = it.next();
System.out.println(element+" ");
}
/**
* 宏观上讲:元素的顺序和存放顺序是不同的。
* 但是在内容不变的前提下,存放顺序是相同的。
* 但在我们使用的时候,要当作是无序的使用。
*/
//使用新循环遍历Set集合
for(String element:set){
System.out.println(element);
}
}
}
package day04;
public class Point {
private int x;
private int y;
public Point(int x, int y) {
super();
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
@Override//删了为false
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
/**
* 若我们不重写hashCode,那么使用的就是Object提供的
* 该方法是返回句柄!换句话说,不同的对象hashCode不同
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Point other = (Point) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
}
package day04;
import java.util.HashSet;
import java.util.Set;
/**
* 测试hashCode对HashSet的影响
* @author Administrator
*
*/
public class DemoHashSet {
public static void main(String[] args) {
Set set = new HashSet();
set.add(new Point(1,2));
set.add(new Point(3,4));
/**
* 查看新创建的对象是否在set中被包含
* 虽然这里是新创建的对象,但是通过散列算法找到了位置后
* 和里面存放的元素进行equals比较为true,所以依然认为是被包含的。
*/
System.out.println(set.contains(new Point(1,2)));
}
}
package day04;
import java.util.HashSet;
import java.util.Set;
/**
* HashSet特点
* @author Administrator
*
*/
public class DemoHashSet2 {
public static void main(String[] args) {
/**
* 定义一个Set集合,允许里面存放Point实例
*/
Set set = new HashSet();
/**
* 创建两个内容一样的对象
*/
Point p1 = new Point(1,2);
Point p2 = new Point(1,2);
System.out.println("p1和p2是否为同一对象:"+(p1==p2));
System.out.println("p1和p2内容是否一样:"+p1.equals(p2));
System.out.println("p1和p2的hashCode是否一样:"+(p1.hashCode()==p2.hashCode()));
/**
* 将两个对象同时放入HashSet集合,看看结果怎么样
*/
set.add(p1);
set.add(p2);
System.out.println("hashset集合的元素数:"+set.size());
for(Point p: set){
System.out.println(p);
}
/**
* 当我们重写了Point的equals方法和hashCode方法后我们发现虽然p1和p2是两个对象,
* 但是当我们将他们同时放入集合时,p2对象并没有被添加进集合。因为p1在放入后,p2放入
* 时根据p2的hashCode计算的位置中p2与该位置的p1的equals比较为true,HashSet认为该
* 对象已经存在,所以拒绝将p2存入集合
*/
set.clear();//清除集合元素
System.out.println("清除了集合。");
/**
* 若我们不重写Point的hashCode方法,但是重写了equals方法,但是重写了equals方法
* 两个对象都可以放入HashSet集合中。因为两个对象具有不同的hashcode值,那么当
* 他们在放入集合时通过hashcode值进行的散列算法结果就不相同,那么他们会被放入
* 集合的不同位置。位置不相同,HashSet则认为他们不同,所以他们可以全部被存入集合。
*/
System.out.println("若不重写hashCode方法,添加的效果。");
set.add(p1);
set.add(p2);
System.out.println("set集合的元素数:"+set.size());
for(Point p:set){
System.out.println(p);
}
set.clear();
System.out.println("清空集合");
/**
* 若我们重写了hashCode但是不重写equals方法。
* hashCode相同的情况下,在存放元素时,他们会在相同的位置,HashSet会在
* 相同位置上将后放入的对象与该位置其他对象依次进行equals比较,若不相同,则将其存入。
* 在同一个位置存入若干元素,这些元素会被放入一个链表中,由此可以看出。我们应该
* 尽量使得多个类的不同对象的hashcode值不同。这样才可以提高HashSet在检索元素时的效率!
* 否则可能检索效率还不如List
*/
set.add(p1);
set.add(p2);
System.out.println("集合的元素数:"+set.size());
for(Point p : set){
System.out.println(p);
}
/**
* 结论:
* 使用HashSet集合存放元素时
* 应保证:equals与hashCode方法在api上定义的要求
* 存放规则:
* 不同对象存放时,不会保存hashCode相同并且equals相同的对象。缺一不可。否则HashSet
* 不认为他们是重复对象。
*/
}
}