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

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);
        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集合的时候提供一个比较器
        SortedSet 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;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值