3、集合框架Set接口
1、Set接口
public interface Set extends Collection 一个不包含重复元素的 collection。更确切地讲,set 不包含满足 e1.equals(e2) 的元素对 e1 和
e2,并且最多包含一个 null 元素。正如其名称所暗示的,此接口模仿了数学上的 set 抽象。
/*
* hashSet
* 1、实现原理,基于哈希表(hashMap)实现
* 2、不允许重复,可以有一个null元素
* 3、不保证顺序恒久不变
* 4、添加元素时把元素作为hashMap的key存储,hashMap的value使用的固定的object对象
* 5、排除重复元素,用equals来判断
*/
private static void hashSet() {
HashSet<String> set=new HashSet<>();
set.add("张飞");
set.add("关羽");
set.add("刘备");
set.add("诸葛亮");
System.out.println(set.size());
String[] name=set.toArray(new String[] {});
for(String s: name) {
System.out.println(s);
}
cat c1=new cat("hh",3);
cat c2=new cat("hh",3);
cat c3=new cat("hh",3);
Set<cat> cats=new HashSet<>();
cats.add(c1);
cats.add(c2);
cats.add(c3);
System.out.println(cats.size());
}
4
关羽
张飞
刘备
诸葛亮
3
2、hashCode深入分析
hashcode() 方法,在object类中定义如下:
public native int hashCode();
hashCode是本地方法,它的实现是根据本地机器相关,当然我们可以在自己写的类中覆盖hashcode()方法,比如
String、Integer、Double。。。。等等这些类都是覆盖了hashcode()方法的。
在java的集合中,判断两个对象是否相等的规则是:
(1)判断两个对象的hashCode是否相等
如果不相等,认为两个对象也不相等,结束
如果相等,转入2
(2)判断两个对象用equals运算是否相等
如果不相等,认为两个对象也不相等
如果相等,认为两个对象相等
(equals()是判断两个对象是否相等的关键)
hashCode不允许重复
public class SetDemo {
/*
* hashSet
* 1、实现原理,基于哈希表(hashMap)实现
* 2、不允许重复,可以有一个null元素
* 3、不保证顺序恒久不变
* 4、添加元素时把元素作为hashMap的key存储,hashMap的value使用的固定的object对象
* 5、排除重复元素,用equals来判断
* 6、判断两个对象是否相同,先判断两个对象的hashCode是否相同(如果两个对象的hashCode相同,
* 不一定是同一个对象,如果不同,那不一定不是同一个对象),如果不同,则两个对象不是同一个对象,
* 如果相同,还要进行equals判断,equals相同则是同一个是对象,反之
* 7、自定义对象要认为属性值都相等时为同一个对象,有这种需求时,那么我们要重写对象所在的类的hashCode和equals方法
*
*
* 小结
* (1)哈希表的储存结构:数组+链表,数组里的每一个元素一链表的形式储存
* (2)如何把对象存储到哈希表中,先计算对象的hashCode值,再用数组的长度求余数,来决定对象要存储在数组中的那个位置
* (3)解决hashSet中重复值使用参考第6点
*/
private static void hashSet() {
HashSet<String> set=new HashSet<>();
set.add("张飞");
set.add("关羽");
set.add("刘备");
set.add("诸葛亮");
System.out.println(set.size());
String[] name=set.toArray(new String[] {});
for(String s: name) {
System.out.println(s);
}
cat c1=new cat("hh",1);
cat c2=new cat("huahau",3);
cat c3=new cat("beibei",2);
cat c4=new cat("hh",1);
//添加一个自定义类型
Set<cat> cats=new HashSet<>();
cats.add(c1);
cats.add(c2);
cats.add(c3);
cats.add(c4);
System.out.println(cats.size());
for(cat s:cats) {
System.out.println(s);
}
System.out.println("c1="+c1.hashCode());
System.out.println("c2="+c2.hashCode());
System.out.println("c3="+c3.hashCode());
System.out.println("c4="+c4.hashCode());
}
package Collection;
public class cat {
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;
}
public cat(String name, int age) {
super();
this.name = name;
this.age = age;
}
public cat() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "cat [name=" + name + ", age=" + age + "]";
}
@Override
public int hashCode() {
final int prime = 31;//系数 31*1+1(age) *31+1
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;
cat other = (cat) 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;
}
}
cat [name=hh, age=1]
cat [name=huahau, age=3]
cat [name=beibei, age=2]
c1=4320
c2=-1206489786
c3=-1392808385
c4=4320
3、TreeSet
public class TreeSet extends AbstractSet implements NavigableSet,
Cloneable, Serializable
基于 TreeMap 的 NavigableSet 实现。使用元素的自然顺序对元素进行排序,或者根据创
建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。
/*
* 有序的,基于TreeMap(二叉树数据结构),对象需要比较大小,通过对象比较器来实现
* 对象比较器还可以用来去除重复元素,如果自定义的数据类,没有实现比较器接口。将无法添加到TreeSet集合中
*/
private static void treeSet() {
TreeSet<cat> tree=new TreeSet<>(new catComparator());
cat c1=new cat("hh",1);
cat c2=new cat("huahau",3);
cat c3=new cat("beibei",2);
cat c4=new cat("hh",1);
tree.add(c1);
tree.add(c2);
tree.add(c3);
tree.add(c4);
System.out.println(tree.size());
for(cat t:tree) {
System.out.println(t);
}
}
import java.util.Comparator;
public class catComparator implements Comparator<cat> {
@Override
public int compare(cat o1, cat o2) {
// TODO Auto-generated method stub
return o1.getAge()-o2.getAge();
}
}
3
cat [name=hh, age=1]
cat [name=beibei, age=2]
cat [name=huahau, age=3]
4、LinkedHashSet
public class LinkedHashSet extends HashSet implements Set, Cloneable,
Serializable
具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现。此实现与 HashSet 的不同之外
在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,
即按照将元素插入到 set 中的顺序(插入顺序)进行迭代。注意,插入顺序不 受在 set
中重新插入的 元素的影响。(如果在 s.contains(e) 返回 true 后立即调用 s.add(e),则
元素 e 会被重新插入到 set s 中。)
/*
* 哈希表和链接列表的实现
* 维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,
即按照将元素插入到 set 中的顺序(插入顺序)进行迭代
*/
private static void linkdeHashSet() {
LinkedHashSet<cat> set=new LinkedHashSet<>();
cat c1=new cat("hh",1);
cat c2=new cat("huahau",3);
cat c3=new cat("beibei",2);
cat c4=new cat("hh",1);
set.add(c1);
set.add(c2);
set.add(c3);
set.add(c4);
for(cat s:set) {
System.out.println(s);
}
}
cat [name=hh, age=1]
cat [name=huahau, age=3]
cat [name=beibei, age=2]