Java学习笔记31(集合框架五:set接口、哈希表的介绍)

2018-01-13 20:35:26来源:cnblogs.com作者:一清人点击

分享

set接口的特点:

1.不包含重复元素

2.set集合没有索引,只能用迭代器或增强for循环遍历

3.set的底层是map集合

方法和Collection的方法基本一样

set接口的实现类HashSet:

1.无序集合

2.可以存入空(null)

3.不可以存在重复元素

示例:

package demo;import java.util.HashSet;import java.util.Iterator;import java.util.Set;public class HashSetDemo {    public static void main(String[] args) {        Set<String> set = new HashSet<String>();        set.add("abc1");        set.add("abc1");        set.add("abc2");        set.add("abc3");        set.add("abc4");        Iterator<String> i1 = set.iterator();        while(i1.hasNext()){            System.out.println(i1.next());        }    }}/*输出:注意:这里的输出特点是无序的abc1abc4abc2abc3*/

set底层数据结构是哈希表:

特点:存储取出都比较快

原理:具体省略,简单说就是链表数组结合体

对象的哈希值:普通的一个整数

可以理解为身份证号,是hashset存储的依据

package demo;public class Person {}
package demo;public class HashDemo {    public static void main(String[] args) {        Person p = new Person();        int i = p.hashCode();        System.out.println(i);        //每次运行都会输出不同的整数,比如1191201656                String s1 = new String("abc");        String s2 = new String("abc");        System.out.println(s1.hashCode());//96354        System.out.println(s2.hashCode());//96354        //这里Stirng重写hashcode方法,有对应的计算公式        //当字符串的内容相同时候,运算结果就相同,因此s1和s2的哈希值相同    }}

哈希表存储过程:


1.调用对象的哈希值

2.集合在容器内搜索有没有重复的哈希值,如果没有,存入新元素,记录哈希值

3.再次存储,重复上边的过程

4.如果有重复的哈希值,调用后来者的equals方法,参数为前来者,结果得到true,集合判断为重复元素,不存入

相同的字符串如果存进去,哈希值相同,equals方法为true,不会存入相同的

只要哈希值相同或者equals方法为true都成立才不会存入,只要其中一条不满足,都会储存

哈希表存储自定义对象:

package demo;public class Person {    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 String toString() {        return this.name + ":" + this.age;    }    public Person() {    }    public Person(String name, int age) {        super();        this.name = name;        this.age = age;    }}
package demo;import java.util.HashSet;public class HashDemo {    public static void main(String[] args) {        HashSet<Person> setPerson = new HashSet<Person>();        setPerson.add(new Person("a",17));        setPerson.add(new Person("b",20));        setPerson.add(new Person("b",20));        setPerson.add(new Person("c",18));        System.out.println(setPerson);        //[c:18, b:20, a:17, b:20]        //发现存入了重复的元素        //所以想办法使name和age相同的Person对象视为同一个对象        //所以需要重写hashcode方法    }}

自己重写:

package demo;public class Person {    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 String toString() {        return this.name + ":" + this.age;    }    public Person() {    }    public Person(String name, int age) {        super();        this.name = name;        this.age = age;    }    public int hashCode(){        return name.hashCode()+age*66;    }    public boolean equals(Object obj) {        if (this == obj) {            return true;        }        if (obj == null) {            return false;        }        if (obj instanceof Person) {            Person p = (Person) obj;            return name.equals(p.name) && age == p.age;        }        return false;    }}

eclipse可以帮助我们写:

package demo;public class Person {    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 String toString() {        return this.name + ":" + this.age;    }    public Person() {    }    public Person(String name, int age) {        super();        this.name = name;        this.age = age;    }    @Override    public int hashCode() {        final int prime = 31;        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;        Person other = (Person) 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;    }}

LinkedHashSet集合:基于链表的哈希表实现,继承HashSet,它具有顺序

示例:

package demo;import java.util.LinkedHashSet;public class LinkedHashSetDemo {    public static void main(String[] args) {        //有序的set        LinkedHashSet<Integer> link = new LinkedHashSet<Integer>();         link.add(1);        link.add(2);        link.add(3);        link.add(4);        System.out.println(link);        //[1, 2, 3, 4]    }}

关于hashcode和equals的一些问题,在面试中会问道:

1.两个对象哈希值相同,那么equals方法一定返回true吗?不一定

取决于如何重写equals,如果重写固定了它返回false,结果就一定是false

2.equals方法返回true,那么哈希值一定相同吗?一定

如果类中定义一个静态变量(static int a = 1),然后重写hashcode返回a+1,那么每一个对象的哈希值都不一样

不过java中规定:对象相等,必须具有相同的哈希码值,所以这里是一定的

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台