每日总结Day07

Map&Stream&递归


目录

Map&Stream&递归

文章目录

一、可变参数

二、Collections

三、Map集合

3.1.概述&常用api

3.2.遍历方式

3.2.1方式1:键找值

3.2.2方式2:键值对

3.2.3方式3:lambda表达式

3.3实现类

3.3.1HashMap

3.3.2LinkedHashMap

3.3.3TreeMap

3.3.4嵌套集合

四、Stream流

4.1.是什么

4.2.获取

4.3.操作

4.4.终结(1)

4.5终结(2)

总结


一、可变参数

可变参数
    就是一种特殊形参,定义在方法、构造器的形参列表里,格式是:数据类型... 参数名称

优点
    特点:可以不传数据给它;可以传一个或者同时传多个数据给它;也可以传一个数组给它。
    好处:常常用来灵活的接收数据。

注意事项
    1. 可变参数在方法内部就是一个数组
    2. 一个形参列表中可变参数只能有一个
    3. 可变参数必须放在形参列表的最后面

代码如下(示例):

public static void main(String[] args) {
        int sum = sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        System.out.println(sum);
    }
    //计算2个整数的和
    //计算3个整数的和
    //计算4个整数的和
	//计算n个整数的和
    public static int sum(int ... num){
        int sum = 0;
        for (int i : num) {
            sum += i;
        }
        return  sum;
    }

二、Collections

Collections
    这是一个用于操作单列集合的工具类
    注意跟Collection的区别(Collection是单列集合的根接口)

常用方法
    static <T> boolean addAll(单列集合,可变参数)   批量添加元素
    static void shuffle(List集合)    打乱List集合元素顺序,每次调用都会打乱
    static <T> void sort(List集合)   List集合进行自然排序
    static <T> void sort(List集合,比较器)  List集合进行比较器排序

代码如下(示例):

public static void main(String[] args) {
        //static <T> boolean addAll(单列集合,可变参数)   批量添加元素
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        Collections.addAll(list, "c", "d", "e");
        System.out.println(list);
        //static void shuffle(List集合)    打乱List集合元素顺序,每次调用都会打乱
        Collections.shuffle(list);
        System.out.println(list);
        //static <T> void  sort(List集合)   List集合进行自然排序
        Collections.sort(list);
        System.out.println(list);
        //排自定义类对象,需要指定排序规则
        List<Student> stuList = new ArrayList<>();
        stuList.add(new Student("zhangsan", 18));
        stuList.add(new Student("wangwu", 22));
        stuList.add(new Student("zhaoliu", 21));
        stuList.add(new Student("lisi", 19));
        stuList.add(new Student("qianqi", 20));
        //static<T> void sort(List集合,比较器);List集合进行比较器排序
        Collections.sort(stuList, (o1, o2) -> o1.getAge() - o2.getAge());
        System.out.println(stuList);
    }

三、Map集合

3.1.概述&常用api

Map
    双列集合根接口,它的功能是全部双列集合都可以继承过来使用的。

常用方法
    V put(K key,V value)   添加元素
    int size()  获取集合的大小
    boolean isEmpty()   判断集合是否为空,为空返回true, 反之
    V get(Object key)   根据键获取对应值
    V remove(Object key)    根据键删除整个元素
    boolean containsKey(Object key)   判断是否包含某个键
    boolean containsValue(Object value)   判断是否包含某个值
    Set<K> keySet()  获取全部键的集合
    Collection<V> values()   获取Map集合的全部值
    void clear()    清空集合

代码如下(示例):

public static void main(String[] args) {
        //向map中存入西游四人组的编号和姓名 001-玄奘  002-悟空  003-悟能  004-悟净
        Map<String,String> map = new HashMap();
        //V put(K key,V value)   添加元素
        map.put("001","玄奘");
        map.put("002","悟空");
        map.put("003","悟能");
        map.put("004","悟净");
        System.out.println(map);
        //int size()	获取集合的大小
        System.out.println(map.size());
        //boolean isEmpty()	判断集合是否为空,为空返回true, 反之
        System.out.println(map.isEmpty());
        //V get(Object key)	根据键获取对应值
        System.out.println(map.get("001"));
        //V remove(Object key)	根据键删除整个元素
        map.remove("001");
        System.out.println(map);
        System.out.println(map.get("001"));
        System.out.println(map.get("002"));
        //boolean containsKey(Object key)	  判断是否包含某个键
        System.out.println(map.containsKey("001"));
        System.out.println(map.containsKey("002"));
        //boolean containsValue(Object value)	  判断是否包含某个值
        System.out.println(map.containsValue("悟空"));
        //Set<K> keySet()	 获取全部键的集合
        Set<String> set = map.keySet();
        set.forEach(s -> System.out.println(s));
        //Collection<V> values()	 获取Map集合的全部值
        Collection<String> values = map.values();
        for (String value : values) {
            System.out.println(value);
        }
        //void clear()	清空集合
        map.clear();
        System.out.println(map);
    }

3.2.遍历方式

3.2.1方式1:键找值

遍历方式1: 先获取Map集合全部的键,再通过遍历键来找值

代码如下(示例):

//遍历方式1: 先获取Map集合全部的键,再通过遍历键来找值
    private static void test1(HashMap<String, String> map) {
        Set<String> strings = map.keySet();
        for (String string : strings) {
            System.out.println(string+"--"+map.get(string));
        }
    }

3.2.2方式2:键值对

遍历方式2: 将map中的所有键值对放入一个set集合中, 然后遍历set集合拿到每个键值对, 再取里面的键值

代码如下(示例):

//遍历方式2: 将map中的所有键值对放入一个set集合中, 然后遍历set集合拿到每个键值对, 再取里面的键值
    private static void test2(HashMap<String, String> map) {
        for (Map.Entry<String, String> stringStringEntry : map.entrySet()) {
            System.out.println(stringStringEntry.getKey()+"--"+stringStringEntry.getValue());
        }
    }

3.2.3方式3:lambda表达式

遍历方式3: Lambda, 使用foreach(BiConsumer bc)

代码如下(示例):

//遍历方式3: Lambda, 使用foreach(BiConsumer bc)
    private static void test3(HashMap<String, String> map) {
        map.forEach((k, v) -> System.out.println(k+"--"+v));
    }

3.3实现类

3.3.1HashMap

实现原理哈希表

现有字符串数组如下:
    String[] bookArr = {"《红楼梦》-曹雪芹","《西游记》-吴承恩","《三国演义》-罗贯中","《水浒传》-施耐庵"};
需求:
    请将字符串中的书名提取为Map集合的键,将作者提取为Map集合的值
    并使用三种不同方式,遍历Map集合打印键值对元素内容

代码如下(示例):

public static void main(String[] args) {
        String[] bookArr = {"《红楼梦》-曹雪芹","《西游记》-吴承恩","《三国演义》-罗贯中","《水浒传》-施耐庵"};
        HashMap<String, String> stringStringHashMap = new HashMap<>();
        for (String keys : bookArr) {
            String[] key = keys.split("-");
            stringStringHashMap.put(key[0],key[1]);
        }
        // 方式一:
        for (String key : stringStringHashMap.keySet()) {
            System.out.println(key+"---"+stringStringHashMap.get(key));
        }
        System.out.println("===============");
        // 方式二:
        for (Map.Entry<String, String> entry : stringStringHashMap.entrySet()) {
            System.out.println(entry.getKey()+"---"+entry.getValue());
        }
        System.out.println("===============");
        // 方式三:
        stringStringHashMap.forEach((k,v)-> System.out.println(k+"---"+v));
    }
需求:创建一个HashMap集合,键是学生对象(Student),值是籍贯(String)。存储三个键值对元素,并遍历

代码如下(示例):

public class Demo4 {
    public static void main(String[] args) {
        //1. 创建一个Map集合
        Map<Student, String> map = new HashMap<>();
        //2. 存储三个学生和地址
        Student s1 = new Student("张三",18);
        Student s2 = new Student("李四",19);
        Student s3 = new Student("王五",20);
        map.put(s1,"北京");
        map.put(s2,"天津");
        map.put(s3,"上海");
        //3. 遍历打印
        for (Student students : map.keySet()) {
            System.out.println(students+"--"+map.get(students));
        }
        for (Map.Entry<Student, String> students : map.entrySet()) {
            System.out.println(students.getKey()+"---"+students.getValue());
        }
        map.forEach((student, s) -> System.out.println(student+"---"+s));
    }
}
class Student {
    private String name;
    private int age;
    public Student() {
    }
    public Student(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;
        Student student = (Student) o;
        return age == student.age && Objects.equals(name, student.name);
    }
    @Override
    public int hashCode() {
        return Objects.hash(name, 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 String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

3.3.2LinkedHashMap

LinkedHashMap :有序、不重复
    底层数据结构依然是基于哈希表实现的,只是每个键值对元素又额外的多了一个双链表的机制记录元素顺序(保证有序)。
    实际上:原来学习的LinkedHashSet集合的底层原理就是LinkedHashMap

代码如下(示例):

public static void main(String[] args) {
        //创建LinkedHashMap
        LinkedHashMap<String,String> map = new LinkedHashMap();
        //保存数据
        map.put("a","a");
        map.put("b","b");
        map.put("c","c");
        //观察顺序
        System.out.println(map);
    }

3.3.3TreeMap

需求:创建一个TreeMap集合,键是学生对象(Student),值是籍贯(String)。
        学生属性姓名和年龄,按照年龄进行排序并遍历。

代码如下(示例):

public class Demo6 {
    private String put;
    public static void main(String[] args) {
        //创建集合
        Map<Teacher, String> map = new TreeMap<>((o1, o2) -> {
            if(o1.equals(o2)){
                return 0;
            }
            return o1.getAge() > o2.getAge() ? 1 :-1;
        });
        map.put(new Teacher("张三", 21), "河北");
        map.put(new Teacher("李四", 20), "山东");
        map.put(new Teacher("王五", 19), "山西");
        map.put(new Teacher("赵六", 21), "河南");
        map.forEach((k, v) -> {
            System.out.println(k + "-----" + v);
        });
    }
}
class Teacher {
    private String name;
    private int age;
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Teacher teacher = (Teacher) o;
        return age == teacher.age && Objects.equals(name, teacher.name);
    }
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
    public Teacher() {
    }
    public Teacher(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 String toString() {
        return "Teacher{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

3.3.4嵌套集合

集合嵌套
    要求在程序中记住如下省份和其对应的城市信息,记录成功后,要求可以查询出湖北省的城市信息。

数据
    江苏省 = "南京市","扬州市","苏州市","无锡市","常州市"
    湖北省 = "武汉市","孝感市","十堰市","宜昌市","鄂州市"
    河北省 = "石家庄市","唐山市","邢台市","保定市","张家口市"

分析:
    定义一个Map集合,键用表示省份名称,值表示城市名称,注意:城市会有多个。 Map<String,List<String>>
    根据“湖北省”这个键获取对应的值展示即可。

代码如下(示例):

public static void main(String[] args) {
        String str1 = "江苏省";
        List<String> list1 = List.of("南京市","扬州市","苏州市","无锡市","常州市");
        Map<String, List<String>> map = new HashMap<>();
        map.put(str1,list1);
        String str2 = "湖北省";
        List<String> list2 = List.of("武汉市","孝感市","十堰市","宜昌市","鄂州市");
        map.put(str2, list2);
        String str3 = "河北省";
        List<String> list3 = List.of("石家庄市","唐山市","邢台市","保定市","张家口市");
        map.put(str3, list3);
        System.out.println(map.get("湖北省"));
    }

四、Stream流

4.1.是什么

Stream流
    Jdk8开始新增的一套API,可以用于操作集合或者数组的数据

优势
    代码更简洁,可读性更好

使用流程
    集合/数组/…---->获取Stream流---->对流中的数据进行各种操作---->结果获取
                                   (排序、过滤、去重等等)     (收集、打印、统计)

4.2.获取

使用流程
    集合/数组/…---->获取Stream流---->对流中的数据进行各种操作---->结果获取
                                   (排序、过滤、去重等等)     (收集、打印、统计)

如何获取Stream流
    Collection集合:
        单列集合都支持一个stream()方法,它可以直接获取集合的Stream流
    数组:
        Arrays.stream(数组)
    零散数据:
        Stream.of(T... values)
    Map
        双列集合并没有提供直接获取Stream流的方法,他需要间接获取

代码如下(示例):

public static void main(String[] args) {
        //"玄奘", "悟空", "悟能", "悟净"
        Collection<String> list = new ArrayList<>();
        list.add("玄奘");
        list.add("悟空");
        list.add("悟能");
        list.add("悟净");
        //Collection集合: 单列集合都支持一个stream()方法,它可以直接获取集合的Stream流
        Stream<String> stream = list.stream();
        stream.forEach(s -> System.out.println(s));
        System.out.println("-------------------------------------------------");
        //数组:Arrays.stream(数组)
        String[] arr = {"玄奘", "悟空", "悟能", "悟净"};
        Stream<String> stream1 = Arrays.stream(arr);
        stream1.forEach(s -> System.out.println(s));
        System.out.println("-------------------------------------------------");
        //零散数据:Stream.of(T... values)
        Stream<String> stream2 = Stream.of("玄奘", "悟空", "悟能", "悟净");
        stream2.forEach(s -> System.out.println(s));
        System.out.println("-------------------------------------------------");
        //Map:双列集合并没有提供直接获取Stream流的方法,他需要间接获取
        Map<String,String> map = new HashMap<>();
        map.put("001","玄奘");
        map.put("002","悟空");
        map.put("003","悟能");
        map.put("004","悟净");
        map.keySet().stream().forEach(s -> System.out.println(s));
        map.entrySet().stream().forEach(entry -> System.out.println(entry.getKey()+"--"+entry.getValue()));
    }

4.3.操作

中间方法
    对stream流进行操作的方法, 他们调用完成后会返回新的Stream流,可以继续使用(支持链式编程)。

常见的中间方法
    Stream<T> filter(Predicate<? super T> p) 按照规则过滤,保留满足条件的元素
    Stream<T> sorted() 升序排序
    Stream<T> sorted(Comparator<? super T> c) 按照规则排序
    Stream<T> limit(long maxSize) 截取
    Stream<T> skip(long n)  跳过
    Stream<R> map(Function<? super T, extends R> mapper) 对元素进行加工,并返回对应的新流
    Stream<T> distinct() 去重
    static <T> Stream<T> concat(Stream a,Stream b) 合并流

代码如下(示例):

public static void main(String[] args) {
        List<Integer> list = List.of(61, 57, 66, 77, 88, 44, 100, 89, 97, 47, 70);
        //需求1: 找出所有及格的分数,并打印
        list.stream()
                        .filter(e -> e>=60)
                                .forEach(System.out::println);
        System.out.println("=================");
        //需求2: 找出所有及格的分数, 正序排列, 打印输出
        list.stream()
                        .filter(e -> e>=60)
                                .sorted()
                                        .forEach(System.out::println);
        System.out.println("=================");
        //需求3: 找出所有及格的分数, 倒序排列, 打印输出
        list.stream()
                        .filter(e -> e>=60)
                                .sorted((o1,o2) -> o2-o1)
                                        .forEach(System.out::println);
        System.out.println("=================");
        //需求4: 找出所有及格的分数, 倒序排列, 取前3名, 打印输出
        list.stream()
                        .filter(e -> e>=60)
                                .sorted((o1,o2) -> o2-o1)
                                        .limit(3)
                                                .forEach(System.out::println);
        System.out.println("=================");
        //需求5: 找出所有及格的分数, 倒序排列, 取前4-6名, 打印输出
        list.stream()
                        .filter(e -> e>=60)
                                .sorted((o1,o2) -> o2-o1)
                                        .skip(3)
                                                .limit(3)
                                                        .forEach(System.out::println);
        System.out.println("=================");
        //需求6:  找出所有及格的分数, 倒序排列, 取前4-6名, 将每个人的分数加10分, 打印输出
        list.stream()
                        .filter(e -> e>=60)
                                .sorted((o1,o2) -> o2-o1)
                                        .skip(3)
                                                .limit(3)
                                                        .map(e -> e+10)
                                                                .forEach(System.out::println);
        System.out.println("=================");
        //需求7: 将下面两个集合中的元素进行合并去重
        List<Integer> list1 = List.of(1, 2, 3);
        List<Integer> list2 = List.of(3, 4, 5);

        Stream.concat(list1.stream(),list2.stream())
                .forEach(System.out::println);
        System.out.println("=================");
        Stream.concat(list1.stream(),list2.stream())
                .distinct()
                .forEach(System.out::println);
    }

4.4.终结(1)

终结方法
    调用完成后,不会返回新Stream了,没法继续使用流了。
    它的作用是对流中的数据进行筛选(遍历、最大、最小、统计个数)
    
常用方法
    void forEach(Consumer consumer)  遍历流中的数据
    long count() 统计流中元素的个数
    Optional max(Comparator<? super T> comparator) 获取流中的最大值
    Optional min(Comparator<?super T> comparator) 获取流中的最小值

代码如下(示例):

public class Demo4 {
    public static void main(String[] args) {
        List<Student> list = List.of(
                new Student("玄奘", 60, 165.5),
                new Student("悟空", 50, 175.5),
                new Student("悟能", 55, 145.5),
                new Student("悟净", 40, 185.5)
        );
        //1. 打印出集合中所有元素
        list.stream().forEach(s -> System.out.println(s));
        //2. 统计出身高不足170的人数
        System.out.println(list.stream().count());
        //3. 请找出年龄最大的对象, 并输出(了解)
        Optional<Student> max = list.stream().max((s1, s2) -> s1.getAge() - s2.getAge());
        Student student = max.get();
        System.out.println(student);
        //4. 请找出身高最高的对象, 并输出(了解)
        Optional<Student> max1 = list.stream().max((s1, s2) -> s1.getHeight() > s2.getHeight() ? 1 : -1);
        Student student1 = max1.get();
        System.out.println(student1);
    }
}

class Student {
    private String name;
    private int age;
    private double height;
    public Student() {
    }
    public Student(String name, int age, double height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }
    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 double getHeight() {
        return height;
    }
    public void setHeight(double height) {
        this.height = height;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", height=" + height +
                '}';
    }
}

4.5终结(2)

终结方法
    调用完成后,不会返回新Stream了,没法继续使用流了。
    它的作用是用来收集Stream流的结果转回到集合或者数组中去返回。

常见方法
    R collect(Collector collector); 将流中数据收集到指定集合,参数传递Collectors工具类调用对应方法
        Collectors.toList()
        Collectors.toSet()
        Collectors.toMap()
    Object[] toArray();

代码如下(示例):

public class Demo5 {
    public static void main(String[] args) {
        List<Teacher> list = List.of(
                new Teacher("玄奘", 60, 165.5),
                new Teacher("悟空", 50, 175.5),
                new Teacher("悟空", 50, 175.5),
                new Teacher("悟能", 55, 145.5),
                new Teacher("悟净", 40, 185.5));
        //1. 请找出身高超过170的教师, 并放到一个新数组中
        Object[] array = list.stream()
                .filter(e -> e.getHeight() > 170)
                .toArray();
        System.out.println(Arrays.toString(array));
        //2. 请找出身高超过170的教师, 并放到一个新List集合中
        List<Teacher> collect = list.stream()
                .filter(e -> e.getHeight() > 170)
                .collect(Collectors.toList());
        System.out.println(collect);
        //3. 请找出身高超过170的教师, 并放到一个新Set集合中
        Set<Teacher> collect1 = list.stream()
                .filter(e -> e.getHeight() > 170)
                .collect(Collectors.toSet());
        System.out.println(collect1);
        //4. 请找出所有的教师的姓名和身高, 放到一个新Map集合中
        Map<String, Double> collect2 = list.stream()
                .distinct()
                .collect(Collectors.toMap(e -> e.getName(), e -> e.getHeight()));
        System.out.println(collect2);
    }
}
class Teacher {
    private String name;
    private int age;
    private double height;
    public Teacher() {
    }
    public Teacher(String name, int age, double height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }
    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 double getHeight() {
        return height;
    }
    public void setHeight(double height) {
        this.height = height;
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Teacher teacher = (Teacher) o;
        return age == teacher.age && Double.compare(teacher.height, height) == 0 && Objects.equals(name, teacher.name);
    }
    @Override
    public int hashCode() {
        return Objects.hash(name, age, height);
    }
    @Override
    public String toString() {
        return "Teacher{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", height=" + height +
                '}';
    }
}


总结

以上就是今天学习的内容。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值