Java基础复习——DAY9(Set;泛型;Map)

集合进阶

1. 集合知识回顾

集合类特点:提供一个存储空间可变的存储模型,存储的数据容量可以随时改变

单列集合(Collection)和双列集合(Map)

体系结构
在这里插入图片描述

Set

1.集合概述和特点

  • 元素不重复
  • 没有索引,不能普通for循环,可以用增强for
package arrays;

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

public class SetDemo {
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();//HashSet对集合迭代顺序不保证
        set.add("hello");
        set.add("world");
        set.add("java");

        //增强for遍历
        for(String s :set){
            System.out.println(s);
            //world
            //java
            //hello
        }

    }
}

2. 哈希值

  • 哈希值:jdk根据对象的地址或者字符串或者数字,算出来的int类型的数值
  • Object类有一个方法:public int hashCode() 返回对象的哈希值

对象哈希值的特点:

  • 默认情况下,不同对象的哈希值不同,可以通过重写hashCode()实现哈希值相同
  • 同一个对象多次调用hashCode()方法返回的哈希值是相同的

3. HashSet集合概述和特点

  • 底层结构,哈希表

  • 不保证顺序

  • 没索引,不能普通for循环遍历

  • 不重复

(呀呦,不和上面一样)

package arrays;

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

public class SetDemo {
    public static void main(String[] args) {
        HashSet<String> set = new HashSet<>();//HashSet对集合迭代顺序不保证
        set.add("hello");
        set.add("world");
        set.add("java");

        //增强for遍历
        for(String s :set){
            System.out.println(s);
            //world
            //java
            //hello
        }

    }
}

4. HashSet集合保证元素唯一性源码分析

在这里插入图片描述

5. 数据结构——哈希表

  • 底层采用链表+数组,可以说是一个元素为链表的数组

在这里插入图片描述

HashSet存储学生信息

  • 重写hashCode()和equals()
package arrays;

import java.util.Objects;

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

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.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 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 && Objects.equals(name, student.name);
    }

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

package arrays;

import java.util.HashSet;

public class SetDemo {
    public static void main(String[] args) {
        HashSet<Student> hs = new HashSet<>();//
        Student s1 = new Student("wts", 20);
        Student s2 = new Student("xwb", 30);
        Student s3 = new Student("cyc", 40);
        Student s4 = new Student("cyc", 40);//重复

        hs.add(s1);
        hs.add(s2);
        hs.add(s3);
        hs.add(s4);

        //增强for遍历
        for (Student s : hs) {
            System.out.println(s.getName() + "," + s.getAge());
            //xwb,30
            //cyc,40
            //wts,20
        }
    }
}

6. LinkedHashSet集合概述和特点

  • 哈希表和链表实现的Set接口,具有可预测的迭代顺序
  • 由链表保证元素有序,(存储和取出顺序一致)
  • 哈希表保证唯一
package arrays;

import java.util.LinkedHashSet;

public class SetDemo {
    public static void main(String[] args) {
        LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();
        linkedHashSet.add("hello");
        linkedHashSet.add("world");
        linkedHashSet.add("java");

        for (String s : linkedHashSet) {
            System.out.println(s);
            //hello
            //world
            //java
        }
    }
}

7. TreeSet集合概述和特点

  • 元素有序,不是存储和取出顺序一致,而是按照一定的规则进行排序,取决于构造方法
    TreeSet():根据其元素自然排序进行排序
    TreeSet(Comparator comparator):根据指定比较器进行排序
  • 没有索引,不能普通for
  • 不重复

注意:所有基本类型存储是用它对应的包装类

package arrays;

import java.util.TreeSet;

public class SetDemo {
    public static void main(String[] args) {
        //创建对象  (基本数据类型创建的对象用它的包装类)
        TreeSet<Integer> ts = new TreeSet<>();
        ts.add(50);
        ts.add(40);
        ts.add(10);
        ts.add(30);
        ts.add(20);

        ts.add(10);//重复不录入

        for (Integer i : ts) {
            System.out.println(i);//自然排序
            //10
            //20
            //30
            //40
            //50
        }
    }
}

8. 自然排序Comparator的使用

  • 用TreeSet集合存储自定义对象时,无参构造方法使用的是自然排序对元素进行排序的
  • 自然排序,就是让所有元素所属的类实现Comparable接口,重写comparableTo()方法
  • 重写是按照要求

案例:存储学生对象,年龄从小到达输出

package arrays;

public class Student implements Comparable<Student> { //学生类实现Comparable接口
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.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(Student s) {
        //return 0;//0只添加了第一个(认为s2和s1是同一个元素 );1升序存储;-1降序存储
        //按照年龄从小到大
        int num = this.age - s.age;//this表示存入的元素,(拿s2和s1说,s1先存进去了,s2后存进去,this就是s2// )
        //int num = s.age - this.age
        int num2 = num == 0 ? this.name.compareTo(s.name) : num;
        return num2;

    }
}

package arrays;

import java.util.TreeSet;

public class SetDemo {
    public static void main(String[] args) {
        //创建对象  (基本数据类型创建的对象用它的包装类)
        //按照年龄从小到大排序
        TreeSet<Student> ts = new TreeSet<>();
        Student s1 = new Student("wts", 20);
        Student s2 = new Student("xwb", 60);
        Student s3 = new Student("wyx", 30);
        Student s4 = new Student("cyc", 40);
        Student s5 = new Student("lx", 20);

        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        ts.add(s5);

        for (Student s : ts) {
            System.out.println(s.getName() + ',' + s.getAge());
//            lx,20
//            wts,20
//            wyx,30
//            cyc,40
//            xwb,60
        }
    }
}

比较器排序Comparator的使用

  • 就是让集合构造方法接受Comparator的实现类对象,重写方法(匿名内部类)
package arrays;

import java.util.Comparator;
import java.util.TreeSet;

public class TreeSetDemo {
    public static void main(String[] args) {
        //创建集合对象
        TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>() {//匿名内部类
            @Override
            public int compare(Student s1, Student s2) {
                //this.age - s.age
                //s1,s2
                int num = s1.getAge() - s2.getAge();
                int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
                return num2;
            }
        });

        //创建学生对象
        //按照年龄从小到大排序
        Student s1 = new Student("wts", 20);
        Student s2 = new Student("xwb", 60);
        Student s3 = new Student("wyx", 30);
        Student s4 = new Student("cyc", 40);
        Student s5 = new Student("lx", 20);
        Student s6 = new Student("lx", 20);//无效

        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        ts.add(s5);

        for (Student s : ts) {
            System.out.println(s.getName() + ',' + s.getAge());
//            lx,20
//            wts,20
//            wyx,30
//            cyc,40
//            xwb,60

        }
    }
}

package arrays;

import java.util.Comparator;
import java.util.TreeSet;

public class TreeSetDemo {
    public static void main(String[] args) {
        //创建集合对象
        TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>() {//匿名内部类
            @Override
            public int compare(Student s1, Student s2) {
                //this.age - s.age
                //s1,s2
                int num = s1.getAge() - s2.getAge();
                int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
                return num2;
            }
        });

        //创建学生对象
        //按照年龄从小到大排序
        Student s1 = new Student("wts", 20);
        Student s2 = new Student("xwb", 60);
        Student s3 = new Student("wyx", 30);
        Student s4 = new Student("cyc", 40);
        Student s5 = new Student("lx", 20);
        Student s6 = new Student("lx", 20);//无效

        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        ts.add(s5);

        for (Student s : ts) {
            System.out.println(s.getName() + ',' + s.getAge());
//            lx,20
//            wts,20
//            wyx,30
//            cyc,40
//            xwb,60

        }
    }
}

案例:比较器输出学生成绩(条件:总分降序,语文成绩,姓名)

package arrays;

public class Student {
    private String name;
    private int chinese;
    private int math;

    public Student() {
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getChinese() {
        return chinese;
    }

    public void setChinese(int chinese) {
        this.chinese = chinese;
    }

    public int getMath() {
        return math;
    }

    public void setMath(int math) {
        this.math = math;
    }

    public int getsum() {
        return this.chinese + this.math;
    }
}

package arrays;

import java.util.Comparator;
import java.util.TreeSet;

public class TreeSetDemo {
    public static void main(String[] args) {
        //创建对象,运用比较器删选
        TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                //主要条件
                int num = s2.getsum() - s1.getsum();
                //次要条件
                int num2 = num==0?s1.getChinese()-s2.getChinese():num;
                int num3 = num2==0?s1.getName().compareTo(s2.getName()):num2;
                return num3;
            }
        });

        //创建学生
        Student s1 = new Student("wts",80,90);
        Student s2 = new Student("wts",84,82);
        Student s3 = new Student("wts",52,63);
        Student s4 = new Student("wts",55,46);
        Student s5 = new Student("wts",76,43);

        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        ts.add(s5);

        for(Student s:ts){
            System.out.println(s.getName()+','+s.getChinese()+','+s.getMath()+','+s.getsum());
        }
    }
}

案例:随机数集合输出

package arrays;

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

public class TreeSetDemo {
    public static void main(String[] args) {
        //创建set对象
        //Set<Integer> set = new HashSet<>();//无序输出
        Set<Integer> set = new TreeSet<>();//升序输出
        
        //创建random随机数
        Random r = new Random();

        //判断集合长度是否小于10,产生一个随机数增加到
        while (set.size()< 10){
            set.add(r.nextInt(20)+1); //[1,21)  1~20之间的数

        }
        for(Integer i:set){
            System.out.println(i);
        }
    }
}

泛型

本质:参数化类型,使用或者调用传入具体类型
格式

  • <类型>,形参
  • <类型1,类型2> , 形参
  • 将来具体调用时给定的类型可以看作实参,并且实参只能是引用数据类型
  • 把运行问题提前到编译期间,避免强制转换

1. 泛型类

感觉是模板

package arrays;

public class Generic <T>{
    private T t;

    public Generic() {
    }

    public Generic(T t) {
        this.t = t;
    }

    public T getT() {
        return t;
    }

    public void setT(T t) {
        this.t = t;
    }
}

package arrays;

public class Demo {
    public static void main(String[] args) {
        Generic<String> s = new Generic<>();
        s.setT("wts");
        Generic<Integer> i = new Generic<>();
        i.setT(20);
        System.out.println(s.getT() + ',' + i.getT());
    }
}

2. 泛型方法

package arrays;

public class Generic {
    public <T> void show(T t){
        System.out.println(t);
    }
}

package arrays;

public class Demo {
    public static void main(String[] args) {
        Generic g = new Generic();
        g.show("wts");//wts
        g.show(20);//20
        g.show(12.25);//12.25
        g.show(true);//true
    }
}

3. 泛型接口

package arrays;
//泛型接口
public interface Generic <T> {
    void show(T t);
}

package arrays;
//接口的实现泛型类
public class GenericImpl<T> implements Generic<T>{
    @Override
    public void show(T t) {
        System.out.println(t);
    }
}

package arrays;
/*测试*/
public class Demo {
    public static void main(String[] args) {
        Generic<String> g = new GenericImpl<>();
        g.show("wts");//wts
        Generic<Integer> g2 = new GenericImpl<>();
        g2.show(200);//200
    }
}

4.类型通配符

为了表示各种泛型List的父类,用类型通配符

  • 类型通配符<?>

  • List<?>:表示元素类型位置的List,他的元素可以匹配任何的类型

  • 仅表示各种泛型List的父类,不能添加元素

不希望List<?>是任何泛型List的父类,只希望是一个泛型List的父类,用类型通配符上限

  • <? extends 类型>
  • List<? extends Number> 表示Number或其子类

类型通配符下限

  • <? super 类型>
  • List<? super Number> 表示Number或其父类

感觉没啥用

5. 可变参数

  • 可变参数,其实是个数组
  • 如果一个方法有多个参数,包含可变参数,可变参数放最后
  • public static int sum(int b,int ...a) {...}
package arrays;

public class Demo {
    public static void main(String[] args) {
        System.out.println(sum(10, 20, 30));//60
        System.out.println(sum(10, 10, 10, 10, 10));//50
    }

    //public static int sum(int b ,int... a) {
    public static int sum(int... a) {
        int n = 0;
        for (int i : a) {//增强for 不太熟啊!
            n += i;
        }
        return n;
    }
}
  • Arrays工具类有一个静态的方法
    public static List asList(T …a):返回指定数组支持的固定大小的列表。不能增删,只能改
       List<String> list = Arrays.asList("hello","world","java");//[hello, world, java]

  • List接口中有一个静态的方法
    public static List of <E …elements>:返回含任意元素的不变的列表
    不能增删改
        List<String> list1 = List.of("wen","tian","sheng");//[wen,tian,sheng]

  • Set接口有一个静态的方法
    public static Set of <E …elements>:返回一个任意数量的不可变的集合不能增删改,不能重复
 Set<String> set = Set.of("wen", "tian", "sheng");//[tian, wen, sheng]
        System.out.println(set);

Map集合

1. Map集合的概述和使用

概述:

  • Interface Map< K, V>
  • 一键一值,不能包含重复的键
  • 举例:学生学号和姓名

创建Map集合的对象

  • 多态
  • 具体实现类HashMap
package arrays;

import java.util.HashMap;
import java.util.Map;

public class Demo {
    public static void main(String[] args) {
        //创建集合对象
        Map<String,String> map = new HashMap<>();
        //V put<K,V>,指定元素和指定键关联,第一次赋值,第二次用就是覆盖
        map.put("cczu001","wts");
        map.put("cczu002","cyc");
        map.put("cczu003","wyx");
        map.put("cczu001","???");//覆盖了上一个键

        //输出集合对象
        System.out.println(map);
        //{cczu002=cyc, cczu001=???, cczu003=wyx}
    }
}

2. Map集合的基本功能

在这里插入图片描述

3. Map集合的获取功能

在这里插入图片描述

package arrays;

import java.util.*;

public class Demo {
    public static void main(String[] args) {
        //创建集合对象
        Map<String, String> map = new HashMap<>();

        map.put("001", "零零一");
        map.put("002", "零零二");
        map.put("003", "零零三");

        //根据键获取值
        System.out.println(map.get("001"));//零零一

        //获取所有键
        Set<String> keyset = map.keySet();
        for (String s : keyset) {
            System.out.print(s + ' ');//001 002 003
        }

        System.out.println();

        //获取所有值
        Collection<String> values = map.values();
        for (String ss : values) {
            System.out.print(ss + ' ');//零零一 零零二 零零三
        }
    }
}

4. Map遍历

4.1 方式1

在这里插入图片描述

package arrays;

import java.util.*;

public class Demo {
    public static void main(String[] args) {
        //创建集合对象
        Map<String, String> map = new HashMap<>();

        map.put("001", "零零一");
        map.put("002", "零零二");
        map.put("003", "零零三");

        //遍历
        Set<String> keyset = map.keySet();
        for (String key : keyset) {
            String value = map.get(key);
            System.out.println(key + ',' + value);
        }
       			 //001,零零一
				//002,零零二
				//003,零零三
    }
}

4.2 方式2

在这里插入图片描述

package arrays;

import java.util.*;

public class Demo {
    public static void main(String[] args) {
        //创建集合对象
        Map<String, String> map = new HashMap<>();

        map.put("001", "零零一");
        map.put("002", "零零二");
        map.put("003", "零零三");

        //获取键值对 对象集合
        for (Map.Entry<String, String> me : map.entrySet()) {
            System.out.print(me.getKey());
            System.out.print(',');
            System.out.println(me.getValue());
            //001,零零一
//            002,零零二
//            003,零零三
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值