Set集合-可变参数-Collections工具类

Set

java.util.Set接口 extends Collection接口
Set接口的特点:不允许存储重复的元素,没有索引,没有带索引的方法,也不能使用普通的for循环进行遍历
java.util.HashSet集合,implements Set接口

HashSet特点:

1、不允许存储重复的元素
2、没有索引,没有带索引的方法,也不能使用普通的for循环遍历
3、是一个无序的集合,存储元素和取出元素的顺序可能不一致
4、底层是一个哈希表结构(查询的速度非常的快)

public class Demo1Set {
    public static void main(String[] args) {
        Set<Integer> set = new HashSet<>();
        //使用add方法往集合中添加元素
        set.add(1);
        set.add(3);
        set.add(2);
        set.add(1);
        //使用迭代器遍历set集合
        Iterator<Integer> it = set.iterator();
        while(it.hasNext()){
            Integer n = it.next();
            System.out.println(n);//123  重复的1没有存进去,顺序也不一样
        }
        //使用增强for循环
        for (Integer i : set) {
            System.out.println(i);//123
        }
    }
}

哈希表

JDK1.8之前,底层使用数组+链表组成,JDK1.8之后,底层采用数组+链表+红黑树组成。

哈希值

哈希值是JDK根据对象的地址,按照某种规则算出来的int类型的数值。
同一个对象多次调用hashCode()方法返回的哈希值是相同的,默认情况下,不同对象的哈希值是不同的。
哈希值:是一个10进制的整数,由系统随机给出(就是对象的地址值,是一个逻辑地址,是模拟出来得到的地址,不是数据实际存储的地址)
在Object类有一个方法,可以获取对象的哈希值
int hashCode() 返回该对象的哈希码值
hashCode方法的源码:
public native int hashCode();
native:代表该方法调用的是本地操作系统的方法

public class Demo01HashCode {
    public static void main(String[] args) {
        //Person类继承了Object类,所以可以使用Object类hashCode方法
        Person p1 = new Person();
        int h1 = p1.hashCode();
        System.out.println(h1);//189568618

        Person p2 = new Person();
        int h2 = p2.hashCode();
        System.out.println(h2);//793589513

        //String类的哈希值 String类重写了Object类的hashCode方法
        String s1 = new String("abc");
        String s2 = new String("abc");
        System.out.println(s1.hashCode());//96354
        System.out.println(s2.hashCode());//96354

        System.out.println("重地".hashCode());//1179395
        System.out.println("通话".hashCode());//1179395
    }
}
HashSet集合存储数据的结构

在这里插入图片描述

Set集合不允许重复元素的原理
public class Demo02HashSetSaveString {
    public static void main(String[] args) {
        //创建HashSet集合对象
        HashSet<String> set = new HashSet<>();
        String s1 = new String("abc");
        String s2 = new String("abc");
        set.add(s1);
        set.add(s2);
        set.add("重地");
        set.add("通话");
        set.add("abc");
        System.out.println(set);//[重地, 通话, abc]
    }
}

在这里插入图片描述

HashSet存储自定义类型元素

在给HashSet中存放自定义类型元素时,需要重写对象中的hashCode和equals方法,建立自己的比较方式,才能保证HashSet集合中的对象唯一
HashSet存储自定义类型元素
Set集合保存元素唯一:
存储的元素(String,Integer,…Student,Person…),必须重写hashCode和equals方法
要求:
同名和同年龄的人,视为同一个人,只能存储一次
重写hashCode和equals方法之前
在这里插入图片描述

重写hashCode和equals方法之后
在这里插入图片描述

主方法

public class Demo03HashSetSavePerson {
    public static void main(String[] args) {
        //创建一个HashSet集合存储Person
        HashSet<Demo03Person> set = new HashSet<>();
        Demo03Person p1 = new Demo03Person("刘辣子",18);
        Demo03Person p2 = new Demo03Person("刘辣子",18);
        Demo03Person p3 = new Demo03Person("刘辣子",19);
        set.add(p1);
        set.add(p2);
        set.add(p3);
        System.out.println(set);

    }
}

Person类

import java.util.Objects;

public class Demo03Person {
    private String name;
    private int age;

    public Demo03Person() {
    }

    public Demo03Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Demo03Person that = (Demo03Person) o;
        return age == that.age && Objects.equals(name, that.name);
    }

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

    @Override
    public String toString() {
        return "Demo03Person{" +
                "name='" + name + '\'' +
                ", age=" + 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;
    }
}

LinkedHashSet

java.util.LinkedHashSet集合 extends HashSet 集合
LinkedHashSet集合特点:
底层是一个哈希表(数组+链表/红黑树)+链表:多了一层链表(记录元素的存储顺序),可以保证元素有序

public class Demo04LinkHashSet {
    public static void main(String[] args) {
        HashSet<String> set = new HashSet<>();
        set.add("zgDaren");
        set.add("abc");
        set.add("abc");
        set.add("com");
        System.out.println(set);//[com, abc, zgDaren]无序,不允许重复

        LinkedHashSet<String> linked = new LinkedHashSet();
        linked.add("zgDaren");
        linked.add("abc");
        linked.add("abc");
        linked.add("com");
        System.out.println(linked);//[zgDaren, abc, com]有序,不允许重复

    }
}

TreeSet集合概述和特点

不重复、无索引、可排序
可排序:按照元素的大小默认升序(从大到小)排序
TreeSet集合底层是基于红黑树的数据结构实现排序的,增删改查性能都比较好。
TreeSet集合是一定要排序的,可以将元素按照指定的规则进行排序

TreeSet集合默认的规则

对于数值类型:Integer,Double,官方默认按照大小进行升序排序
对于字符串类型:默认按照首字符的编号升序排序
对于自定义类型如student对象,TreeSet无法直接排序。

TreeSet自定义排序规则

1、让自定义的类(如学生类)实现Comparable接口重谢里面的compareTo方法来定制比较规则。
2、TreeSet集合有参数构造器,可以设置Comparator接口对应的比较器对象,来定制比较规则。
两种方式中,关于返回值的规则:
如果认为第一个元素大于第二个元素返回正整数即可。
如果认为第一个元素小于第二个元素返回负整数即可。
如果认为第一个元素等于第二个元素返回0即可,此时TreeSet集合只会保留一个元素,认为两者重复。
注意:如果TreeSet集合存储的对象有实现比较规则,集合也自带比较器,默认使用集合自带的比较器排序。

1、如果希望元素可以重复,又有索引,索引查询要快
使用ArrayList集合,基于数组的。(用的最多)
2、如果希望元素可以重复,又有索引,增删首尾操作快?
用Linkedlist集合,基于链表的。
3、如果希望增删改查都快,但是元素不重复、无序、无索引
用HashSet集合,基于哈希表的
4、如果希望增删改查都快,但是元素不重复、有序、无索引
用LinkedHasdSet集合,基于哈希表和双链表
5、如果要对对象进行排序
用TreeSet集合,基于红黑树,后续也可以用List集合实现排序。

可变参数

可变参数:是JDK1.5之后出现的新特性
使用前提:
当方法的参数列表数据类型已经确定,但是参数的个数不确定,就可以使用可变参数
使用格式:定义方法时使用
修饰符 返回值类型 方法名 (数据类型…变量名){}
可变参数的原理:
可变参数底层就是一个数组,根据传递参数个数不同,会创建不同长度的数组,来存储这些参数
传递的参数个数,可以是0个(不传递),1,2,3…多个
可变参数的注意事项
1、一个方法的参数列表,只能有一个可变参数,数据类型不同也不行
2、如果方法的参数有多个,那么可变参数必须写在参数列表的末尾

public class DemoVarArgs {
    public static void main(String[] args) {
        //int i = add();不传参数
        //int i = add(10);一个参数
        int i = add(10,23,45,66,43,22,56,322,1123);//1710
        System.out.println(i);

        method("abc",8.8,3,12,34,5456);
    }

    //只能有一个可变参数,数据类型不同也不行
    //public static void method(int...a,String...b){}

    //如果方法的参数有多个,那么可变参数必须写在参数列表的末尾
    public static void method(String b,double c,int d,int...a){

    }

    //可变参数的特殊写法(终极)写法
    public static void method1(Object...obj){//Object可以接收任意类型的参数
        return;
    }

    //定义计算(0~n)个整数和的方法
    //已知:计算整数的和,数据类型已经确定int
    //但是参数的个数不确定,不知道要计算几个整数的和,就可以使用可变参数
    //add();就会创建一个长度为0的数组,new int[0]
    //add(10);就会创建一个长度为1的数组,存储传递过来的参数 new int []{10}
    add(10,20);就会创建一个长度为1的数组,存储传递过来的参数 new int []{10,20}
    public static int add(int...arr){
        System.out.println(arr);//底层是一个数组,[I@10f87f48
        System.out.println(arr.length);//0,长度为0的数组,如果是一个参数长度就为1,两个为2...
        //定义一个初始化的变量,记录累加求和
        int sum = 0;
        //遍历数组,获取数组中的每一个元素
        for (int i : arr){
            sum += i;//累加求和
        }
        //把求和结果返回
        return sum;
    }

   /* //定义一个方法,计算三个int类型整数的和
    public static int add(int a,int b,int c){
        return a+b+c;
    }
    //定义一个方法,计算两个int类型整数的和
    public static int add(int a,int b){
        return a+b;
    }*/
}

java.util.Collection是集合工具类,用来对集合进行操作
public static boolean addAll(Collection c, T…elements):往集合中添加一些元素
public static void shuffle(List<?> list) 打乱顺序:打乱集合顺序

public class Demo01Collections {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        //往集合中添加多个元素
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("e");
        System.out.println(list);//[a, b, c, d, e]

        //public static <T> boolean addAll(Collection<T> c, T...elements):往集合中添加一些元素
        ArrayList<String> list1 = new ArrayList<>();
        Collections.addAll(list1,"a","b","c","d","e");
        System.out.println(list1);//[a, b, c, d, e]
        //public static void shuffle(List<?> list) 打乱顺序:打乱集合顺序
        Collections.shuffle(list);
        System.out.println(list);//[e, a, c, d, b]

    }
}

public static void sort(List list):将集合中的元素按照默认规则排序
注意:该方法的使用中,被排序的集合里边存储元素,必须实现Comparable,重写接口中的方法compereTo定义排序的规则
Comparable接口的排序规则
自己(this)- 参数 升序

public class Demo02Sort {
    public static void main(String[] args) {
        ArrayList<Integer> list01 = new ArrayList<>();
        list01.add(1);
        list01.add(3);
        list01.add(2);
        System.out.println(list01);//[1, 3, 2]

        //public static <T> void sort(List<T> list):将集合中的元素按照默认规则排序
        //静态方法可以直接使用类名来使用
        //参数只能传递list集合,不能传递set集合
        Collections.sort(list01);//默认为升序
        System.out.println(list01);//[1, 2, 3]

        ArrayList<String> list02 = new ArrayList<>();
        list02.add("a");
        list02.add("c");
        list02.add("b");
        System.out.println(list02);//[a, c, b]
        Collections.sort(list02);
        System.out.println(list02);//[a, b, c]

        //使用自定义类
        ArrayList<Person> list03 = new ArrayList<>();
        list03.add(new Person("张三",18));
        list03.add(new Person("李四",28));
        list03.add(new Person("王五",19));
        System.out.println(list03);//[Person{name='张三', age=18}, Person{name='李四', age=28}, Person{name='王五', age=19}]

        Collections.sort(list03);
        System.out.println(list03);//[Person{name='张三', age=18}, Person{name='王五', age=19}, Person{name='李四', age=28}]



    }
}

public class Person implements Comparable<Person>{
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + 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;
    }
    //重写排序的规则
    @Override
    public int compareTo(Person o) {
        //return 0;//返回0是因为认为元素是相同的
        //定义比较的规则,比较两个人的年龄(this,参数Person)
        return this.getAge() - o.getAge();//升序排序年龄
        //return o.getAge() - this.getAge();//降序排序年龄
    }
}

java.utils.Collections集合工具类,用来对集合进行操作
public static void (list list,Comparator< ? super T>):将集合中元素按照指定规则排序)
Comparator和Comparable的区别
Comparable:自己(this)和别人(参数)比较,自己需要实现ComParable接口,重写比较的规则compareTo
Comparator:相当于找也给第三方的裁判,比较两个
Comparator的排序规则o1 - o2升序,o2 - o1;降序

public class Demo03Sort {
    public static void main(String[] args) {
        ArrayList<Integer> list01 = new ArrayList<>();
        list01.add(1);
        list01.add(3);
        list01.add(2);
        System.out.println(list01);//[1, 3, 2]

        Collections.sort(list01, new Comparator<Integer>() {
            //重写比较的规则
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1 - o2;//升序
                //return o2 - o1;//降序
            }
        });
        System.out.println(list01);//[1, 2, 3]

        //使用自定义类
        ArrayList<Student> list02 = new ArrayList<>();
        list02.add(new Student("张三",18));
        list02.add(new Student("李四",28));
        list02.add(new Student("王五",19));
        System.out.println(list02);//[Student{name='张三', age=18}, Student{name='李四', age=28}, Student{name='王五', age=19}]
        Collections.sort(list02, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                //按照年龄升序排序
                return o1.getAge() - o2.getAge();
            }
        });
        System.out.println(list02);//[Student{name='张三', age=18}, Student{name='王五', age=19}, Student{name='李四', age=28}]

        //使用自定义类
        ArrayList<Student> list03 = new ArrayList<>();
        list03.add(new Student("a张三",18));
        list03.add(new Student("李四",28));
        list03.add(new Student("王五",19));
        list03.add(new Student("b王五",18));
        System.out.println(list03);
        Collections.sort(list03, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                //按照年龄升序排序
                int result =  o1.getAge() - o2.getAge();
                //如果两个人年龄想相同,在使用姓名的第一个字比较
                if (result==0){
                    result = o1.getName().charAt(0) - o2.getName().charAt(0);
                }
                return result;
            }

        });
        System.out.println(list03);//按照年龄排序,如果有年龄相同,姓名不同,则哪个在前面哪个就先输出

    }
}

public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + 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;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zgDaren

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值