一篇文章让你精通:java集合讲解(三,Set)

Posted 韶光不负

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一篇文章让你精通:java集合讲解(三,Set)相关的知识,希望对你有一定的参考价值。

一篇文章让你精通:java集合讲解(二,ArrayList)

一篇文章让你精通:java集合讲解(二,LinkList)

上面二个链接,让大家对集合中的List有了一定的了解,如果大家回想要继续加强理解,建议大家打开jdk8下的List源码继续解析一下。废话不多说下面让我们来看看Set的内容吧!

目录

Set

HashSet

linkedHashSet

TreeSet

set的遍历方法(三种方法,无序:不能使用for循环)

练习:set存储自定义类的对象与操作(存储学生信息)

问题发现

解决问题一:在Student类下重写equals与 hashCode方法(缺一不可)。

 解决问题2:在Student在threeSet下重写compareTo的比较方法(按照姓名比较),这样使用treeHash就不会报错了。

报错显示:java.lang.ClassCastException: com.itheima.类名称 cannot be cast to java.lang.Comparable


Set

特点:无序,唯一(数据不重复) 

HashSet

特点:采用HashSet哈希表存储结构。

优点:添加速度快,查询速度快,删除速度快。

缺点:无序

HashSet的常用方法

add()
 

末尾添加元素,
数组能自动装箱:就是数组封装。普通数据类型——>包装类
可以使用一个参数或者二个,一个时,添加元素,二个时,第一个参数:索引,第二个,添加元素
addAll(对象)
addAll(下标,对象)

复制添加对象全部元素,默认在后面添加

当有二个参数后,表示在下标后添加对象全部元素。

remove()当输入的是对象时,删除对象,当输入的是对下标,删除下标,
el1.removeAll(el2)在el1中删除el2中相同的元素。
list.retainAll(list2);在list中查找与list2相同的元素
clear()   清空数组
contains(value)判断是否存在value值,返回布尔值
isEmpty()判断数组是否为空。
size()查看数组中真实存储的元素个数。与数组的length()方法返回不同
toString()遍历数组

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

public class Test {
    public static void main(String[] args)  {
        //创建Set集合数组
        Set<String> set= new HashSet();

        //添加元素
        set.add("javaSE");
        set.add("javaEE");
        set.add("english");
        set.add("中文");
        //可以添加相同的数据,但不会添加到集合中
        set.add("javaSE");

        //查看数量
        System.out.println(set.size());

        //遍历元素
        System.out.println(set);
        for (String ss:set) {
            System.out.println(ss);
        }
        //数据清空
        set.clear();



    }


}

linkedHashSet

HashSet的子类,采用哈希表存储结构,同时使用了链表维护次序,有序(添加顺序)



import java.util.LinkedHashSet;
import java.util.Set;

public class Test {
    public static void main(String[] args)  {
        //创建Set集合数组,有序,但是是存储的先后顺序
        Set<String> set= new LinkedHashSet();

        //添加元素
        set.add("javaSE");
        set.add("javaEE");
        set.add("english");
        set.add("中文");
        //可以添加相同的数据,但不会添加到集合中
        set.add("javaSE");

        //查看数量
        System.out.println(set.size());

        //遍历元素
        System.out.println(set);
        for (String ss:set) {
            System.out.println(ss);
        }
        //数据清空
        set.clear();



    }


}

TreeSet

特点:采用二叉树(红黑树,左子数小于根,右子树大于根,左右平衡)的存储结构

优点:有序,查询速度比List快(按照内容进行查找)

缺点:查询速度比HashSet快

TreeSet的常用方法

add()
 

末尾添加元素,
数组能自动装箱:就是数组封装。普通数据类型——>包装类
可以使用一个参数或者二个,一个时,添加元素,二个时,第一个参数:索引,第二个,添加元素
addAll(对象)
addAll(下标,对象)

复制添加对象全部元素,默认在后面添加

当有二个参数后,表示在下标后添加对象全部元素。

remove()当输入的是对象时,删除对象,当输入的是对下标,删除下标,
el1.removeAll(el2)在el1中删除el2中相同的元素。
list.retainAll(list2);在list中查找与list2相同的元素
clear()   清空数组
contains(value)判断是否存在value值,返回布尔值
isEmpty()判断数组是否为空。
size()查看数组中真实存储的元素个数。与数组的length()方法返回不同
toString()遍历数组

import java.util.Set;
import java.util.TreeSet;

public class Test {
    public static void main(String[] args)  {
        //创建Set集合数组,有序,但是是存储的先后顺序
        Set<String> set= new TreeSet();

        //添加元素
        set.add("javaSE");
        set.add("javaEE");
        set.add("english");
        set.add("中文");
        //可以添加相同的数据,但不会添加到集合中
        set.add("javaSE");

        //查看数量
        System.out.println(set.size());

        //遍历元素
        System.out.println(set);
        for (String ss:set) {
            System.out.println(ss);
        }
        //数据清空
        set.clear();



    }


}

set的遍历方法(三种方法,无序:不能使用for循环)

 //遍历元素 for-each
        System.out.println(set);
        for (String ss:set) {
            System.out.println(ss);
        }
        //遍历元素 迭代器
        Iterator<String> it=set.iterator();
        while (it.hasNext()){
            String elem =it.next();
            System.out.println(elem);
        }
        //遍历元素 lambda表达式
        set.forEach((elem)-> System.out.println(elem+" "));

练习:set存储自定义类的对象与操作(存储学生信息)

一,先定义一个学生的ApI.

(IDEA工具快速生成快捷键:Alt+insert)



import java.util.Objects;

//一个完整的API
public class Student implements Comparable<Student> {
    //姓名
    private String name;
    //性别
    private String sex;
    //年龄
    private int age;
    //分数
    private double score;
    
    //重写TreeSet的比较规则
    @Override
    public int compareTo(Student other){
        return this.name.compareTo(other.name);
    }

    public Student() {
        //无参构造
    }

    public Student(String name, String sex, int age, double soore) {
        //有参构造
        this.name = name;
        this.sex = sex;
        this.age = age;
        this.score = score;
    }

    //生成get方法
    public String getName() {
        return name;
    }

    public String getSex() {
        return sex;
    }

    public int getAge() {
        return age;
    }

    public double getScore() {
        return score;
    }

    //生成set方法
    public void setName(String name) {
        this.name = name;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setScore(double score) {
        this.score = score;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age &&
                Double.compare(student.score, score) == 0 &&
                Objects.equals(name, student.name) &&
                Objects.equals(sex, student.sex);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, sex, age, score);
    }

    //生成toString方法
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\\'' +
                ", sex='" + sex + '\\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }
}

二,进行学生添加到set中


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


public class Test {
    public static void main(String[] args)  {
        //创建Set集合数组,存储学生信息。
        Set<Student> set= new HashSet();

        //使用set存储多个学生信息
        Student stu1= new Student("张三","男",18,60);
        Student stu2= new Student("李四","男",28,75);
        Student stu3= new Student("小明","男",20,90);
        Student stu4= new Student("小美","女",18,100);
        Student stu5= new Student("Jack","女",18,100);
        //插入数据重复的信息看看现象
        Student stu6= new Student("Jack","女",18,100);

        //添加到Set中
        set.add(stu1);
        set.add(stu2);
        set.add(stu3);
        set.add(stu4);
        set.add(stu5);
        set.add(stu6);

        //查看数量
        System.out.println(set.size());

        //遍历元素 for-each
        System.out.println(set);
        for (Student student1:set) {
            System.out.println(student1);
        }
        //遍历元素 迭代器
//        Iterator<Student> it=set.iterator();
//        while (it.hasNext()){
//            Student elem =it.next();
//            System.out.println(elem);
//        }
        //遍历元素 lambda表达式
//        set.forEach((elem)-> System.out.println(elem+" "));

        //数据清空
//        set.clear();
    }
}

问题发现

1,HashSet存储Steing是唯一的,但在存储Student对象时不唯一?

Steing是系统写好的内部类,有equals与 hashCode方法,所以当我们使用时需要重写。

2,当Treeset存储String是有序的,但存储Student对象时却报异常(类型转化异常)?

在Student在threeSet下没有compareTo比较方法?

原因:String是系统类,做了一些其他操作,而student是自定义类,一些操作没有做

解决问题一:在Student类下重写equals与 hashCode方法(缺一不可)。

 @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age &&
                Double.compare(student.score, score) == 0 &&
                Objects.equals(name, student.name) &&
                Objects.equals(sex, student.sex);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, sex, age, score);
    }

现象:

 解决问题2:在Student在threeSet下重写compareTo的比较方法(按照姓名比较),这样使用treeHash就不会报错了。

 //重写TreeSet的比较规则
    @Override
    public int compareTo(Student other){
        return this.name.compareTo(other.name);
    }

报错显示:java.lang.ClassCastException: com.itheima.类名称 cannot be cast to java.lang.Comparable

在使用TreeSet时,发生的报错:原因就是在自定义类在ThreeSet下没有compareTo比较方法?

解决办法:

public class 自定义类 implements Comparable<Student> {
  
    //重写TreeSet的比较规则
    @Override
    public int compareTo(自定义类 other){
        return this.name.compareTo(other.属性);
    }

以上是关于一篇文章让你精通:java集合讲解(三,Set)的主要内容,如果未能解决你的问题,请参考以下文章

一篇文章让你精通:java集合讲解(六,Map)

一篇文章让你精通:java集合讲解(八,集合的解析与总结)

一篇文章让你精通:java集合讲解(五,哈希表)

一篇文章让你精通:java集合讲解(练习处理)

一篇文章让你精通:java集合讲解(二,LinkList)

一篇文章让你精通:java集合讲解