您的位置:首页 > 编程语言 > Java开发

java学习初探十三之集合—Set详解

2017-09-14 23:07 489 查看
1.哈希表/散列表

HashSet底层实际上是一个HashMap。HashMap底层是哈希表/散列表。

哈希表是数组和单向链表的集合。

哈希表本质是一个数组,只不过这个数组中的每个元素又是个单向链表。类似于现实世界中的字典。

final int hash这个是哈希值,是通过key调用hashCode方法得到的值,再通过“哈希算法”得到的值。在单向链表中,每个节点的哈希值是相同的。代表的是数组的下标。注,不同key的获得的hashCode可能相同,也可能不相同。



2.HashSet详解

(1)HashSet底层实际上是一个HashMap,HashMap底层采用了哈希表数据结构。

(2)哈希表又叫散列表,哈希表底层是一个数组,这个数组中每个元素是一个单向链表。每个单向链表都有一个独一无二的hash值,代表数组的下标。在某个单向链表中的每一个节点上的hash值是相等的。hash值实际上是key调用hashCode方法,再通过“hash function”转换成的值。

(3)如何向哈希表中添加元素:

先调用被存储key的hashCode方法,经过某个算法得到hash值,如果在这个哈希表中不存在这个hash值,则直接加入元素。如果该hash值已经存在,继续调用key之间的equals方法,如果equals方法返回false,则将该元素添加。如果equals返回true,则放弃添加该元素。

(4)HashSet其实是HashMap中的key部分。HashSet有什么特点,HashMap中的key应该具有相同的特点。

(5)HashMap和HashSet初始化容量都是16,默认加载因子是0.75。

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class SetTest {
public static void main(String[] args) {
//创建Set集合
Set s=new HashSet();
//无序不可重复
s.add(1);

4000
s.add(1);
s.add(100);
s.add("ok");
s.add(85);
s.add(88);
//遍历
Iterator it=s.iterator();
while(it.hasNext()) {
System.out.println(it.next());//1 100 85 88 ok
}
}
}


关于往Set集合中存储的元素,该元素的hashCode和equals方法:

HashMap中有一个put方法,put(key,value) key是无序不可重复的。

结论:存储在HashSet集合或HashMap集合key部分的元素,需要同时重写public int hashCode()()和public boolean equals(Object o)方法。

hashCode目的:让散列分布均匀。

import java.util.HashSet;
import java.util.Set;

public class SetTset02 {

public static void main(String[] args) {
//创建集合
Set es=new HashSet();
Employee e1=new Employee("1000", "JACK");
Employee e2=new Employee("1000", "JACK");
Employee e3=new Employee("2000", "JIM");
Employee e4=new Employee("2001", "SUN");
Employee e5=new Employee("3000", "ROSE");
Employee e6=new Employee("3001", "COOK");

//添加元素
es.add(e1);
es.add(e2);
es.add(e3);
es.add(e4);
es.add(e5);
es.add(e6);

//重写hashCode和equals方法前        查看集合元素hash值和元素个数
System.out.println(e1.hashCode());//366712642
System.out.println(e2.hashCode());//1829164700
System.out.println(es.size());//6

//重写hashCode和equals方法后        查看集合元素hash值和元素个数
System.out.println(e1.hashCode());//1507423
System.out.println(e2.hashCode());//1507423
System.out.println(es.size());//5

}

}

//根据现实的业务逻辑得知:该公司员工编号是:1000-9999
class Employee{
//编号
String no;
//姓名
String name;
//Constructor
Employee(String no,String name){
this.no=no;
this.name=name;
}
//重写hashCode方法
public int hashCode() {
//以员工编号分组
return no.hashCode();
}
//重写equals方法
//如果员工编号相同,并且名字相同,则是同一个人
public boolean equals(Object o) {
if(this==o) return true;
if(o instanceof Employee) {
Employee e=(Employee)o;
if(e.no.equals(this.no)&&e.name.equals(this.name)) {
return true;
}
}
return false;
}
}


3.SortedSet详解

(1)无序不可重复,但是存进去的元素可以按照元素大小顺序自动排序。

数据结构:二叉树

import java.util.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.TreeSet;

public class SetTest03 {
public static void main(String[] args) throws ParseException {
//创建集合
SortedSet ss=new TreeSet();
//添加元素
ss.add(10);//自动装箱
ss.add(20);
ss.add(15);
ss.add(30);
ss.add(25);
ss.add(9);
//遍历
Iterator it=ss.iterator();
while (it.hasNext()) {
System.out.println(it.next());//9 10 15 20 25 30
}

//String
SortedSet strs=new TreeSet();
strs.add("JACK");
strs.add("SUN");
strs.add("COOK");
strs.add("LUCY");
strs.add("KING");
//遍历
Iterator its=strs.iterator();
while (its.hasNext()) {
System.out.println(its.next());//COOK JACK KING LUCY SUN
}

//Date
String t1="2008-08-08";
String t2="2009-08-08";
String t3="2008-09-08";
String t4="2008-08-09";
String t5="2012-08-08";
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
Date date1=sdf.parse(t1);
Date date2=sdf.parse(t2);
Date date3=sdf.parse(t3);
Date date4=sdf.parse(t4);
Date date5=sdf.parse(t5);
SortedSet strse=new TreeSet();
strse.add(date1);
strse.add(date2);
strse.add(date3);
strse.add(date4);
strse.add(date5);
//遍历
Iterator itst=strse.iterator();
while (itst.hasNext()) {
Object element=itst.next();
if(element instanceof Date) {
Date d=(Date)element;
System.out.println(sdf.format(d));
/*输出结果
2008-08-08
2008-08-09
2008-09-08
2009-08-08
2012-08-08
*/
}
}

}
}


(2)实现Comparable接口

SortedSet集合存储元素为什么可以自动排序?

因为被存储的元素实现了Comparable接口,

SUN编写的TreeSet集合在添加元素的时候,会调用compareTo方法,完成比较。

import java.util.Iterator;
import java.util.SortedSet;
import java.util.TreeSet;

public class SetTest04 {

public static void main(String[] args) {
SortedSet users=new TreeSet();
User u1=new User(15);
User u2=new User(16);
User u3=new User(25);
User u4=new User(13);
User u5=new User(14);
//添加元素
users.add(u1);
users.add(u2);
users.add(u3);
users.add(u4);
users.add(u5);
//实现java.lang.Comparable接口前      遍历
Iterator it=users.iterator();
while (it.hasNext()) {
System.out.println(it.next());
/*
* java.lang.ClassCastException:
* User cannot be cast to java.lang.Comparable
*/

}

//实现java.lang.Comparable接口前      遍历
Iterator it2=users.iterator();
while (it2.hasNext()) {
System.out.println(it2.next());
/*
* User[age=13]
User[age=14]
User[age=15]
User[age=16]
User[age=25]
*/

}

}

}
class User implements Comparable{
int age;
User(int age){
this.age=age;

}
public String toString() {
return "User[age="+age+"]";
}
//实现java.lang.Comparable接口中的compareTo方法
//该方法程序员负责实现,SUN提供的程序已经调用了该方法
//需求:按照User的age年龄排序
public int compareTo(Object o) {
//编写一个比较规则
int age1=this.age;
int age2=((User)o).age;
return age1-age2;
}
}


(3)java.util.Comparator

SortedSet集合做到排序还有另外一个方法java.util.Comparator相比Comparable更为灵活,耦合度较低,推荐使用Copmparator比较器

import java.util.Comparator;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.TreeSet;

public class SetTest05 {

public static void main(String[] args) {

//创建TreeSet集合的时候提供一个比较器
So
a35e
rtedSet products=new TreeSet(new ProductComparator());

//还可以用下面匿名内部类的方式实现比较器,不推荐使用,因为毕竟器不能得到重复利用

/*
SortedSet products=new TreeSet(new Comparator() {
public int compare(Object o1, Object o2) {
double price1=((Product)o1).price;
double price2=((Product)o2).price;
if(price1==price2) {
return 0;
}else if(price1>price2) {
return 1;
}else {
return -1;
}
}
});
*/

Product p1=new Product(3.4);
Product p2=new Product(4.0);
Product p3=new Product(2.0);
Product p4=new Product(3.0);
Product p5=new Product(5.0);

//添加元素
products.add(p1);
products.add(p2);
products.add(p3);
products.add(p4);
products.add(p5);
//遍历
Iterator it =products.iterator();
while (it.hasNext()) {
System.out.println(it.next());
/*
*  输出结果
*  2.0
3.0
3.4
4.0
5.0

*/

}
}

}
class Product{
double price;
public Product(double price) {
this.price=price;
}
public String toString() {
return price+"";

}
}
//单独写一个比较器
class ProductComparator implements Comparator{

//重写:
//需求:按照商品价格排序
public int compare(Object o1, Object o2) {
double price1=((Product)o1).price;
double price2=((Product)o2).price;
if(price1==price2) {
return 0;
}else if(price1>price2) {
return 1;
}else {
return -1;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: