黑马Java——集合进阶(不可变集合、Stream流、方法引用)

目录

一、不可变集合

1、创建不可变集合的应用场景

2、创建不可变集合的书写格式

2.1、不可变的List集合

2.2、不可变的Set集合

2.3、不可变的Map集合

3、小结

二、Stream流

1、体验Stream流的作用

2、Stream流的思想

3、Stream流的使用步骤

3.1、单列集合获取Stream流

3.2、双列集合获取Stream流(先转成keySet()或entrySet())

3.3、数组获取Stream流(Arrays.stream())

3.4、一堆零散数据(Stream.of())

4、Stream流的中间方法

三、方法引用

1、什么是方法引用?

1.1、示例代码

1.2、小结

2、方法引用的分类

2.1、引用静态方法(类名::静态方法)

2.2、引用成员方法(对象::成员方法)

2.3、引用构造方法(类名::new)


一、不可变集合

不可变集合:不可以被修改的集合

1、创建不可变集合的应用场景

2、创建不可变集合的书写格式

2.1、不可变的List集合

import java.util.Iterator;
import java.util.List;public class ImmutableDemo1 {public static void main(String[] args) {/*创建不可变的List集合"张三", "李四", "王五", "赵六"*///一旦创建完毕之后,是无法进行修改的,在下面的代码中,只能进行查询操作List<String> list = List.of("张三", "李四", "王五", "赵六");System.out.println(list.get(0));System.out.println(list.get(1));System.out.println(list.get(2));System.out.println(list.get(3));System.out.println("---------------------------");for (String s : list) {System.out.println(s);}System.out.println("---------------------------");Iterator<String> it = list.iterator();while(it.hasNext()){String s = it.next();System.out.println(s);}System.out.println("---------------------------");for (int i = 0; i < list.size(); i++) {String s = list.get(i);System.out.println(s);}System.out.println("---------------------------");//list.remove("李四");//list.add("aaa");list.set(0,"aaa");}
}

2.2、不可变的Set集合

import java.util.Iterator;
import java.util.Set;public class ImmutableDemo2 {public static void main(String[] args) {/*创建不可变的Set集合"张三", "李四", "王五", "赵六"细节:当我们要获取一个不可变的Set集合时,里面的参数一定要保证唯一性*///一旦创建完毕之后,是无法进行修改的,在下面的代码中,只能进行查询操作Set<String> set = Set.of("张三", "张三", "李四", "王五", "赵六");for (String s : set) {System.out.println(s);}System.out.println("-----------------------");Iterator<String> it = set.iterator();while(it.hasNext()){String s = it.next();System.out.println(s);}System.out.println("-----------------------");//set.remove("王五");}
}

2.3、不可变的Map集合

10个参数以下使用Map.of()

import java.util.Map;
import java.util.Set;public class ImmutableDemo3 {public static void main(String[] args) {/*创建Map的不可变集合细节1:键是不能重复的细节2:Map里面的of方法,参数是有上限的,最多只能传递20个参数,10个键值对细节3:如果我们要传递多个键值对对象,数量大于10个,在Map接口中还有一个方法*///一旦创建完毕之后,是无法进行修改的,在下面的代码中,只能进行查询操作Map<String, String> map = Map.of("张三", "南京", "张三", "北京", "王五", "上海","赵六", "广州", "孙七", "深圳", "周八", "杭州","吴九", "宁波", "郑十", "苏州", "刘一", "无锡","陈二", "嘉兴");Set<String> keys = map.keySet();for (String key : keys) {String value = map.get(key);System.out.println(key + "=" + value);}System.out.println("--------------------------");Set<Map.Entry<String, String>> entries = map.entrySet();for (Map.Entry<String, String> entry : entries) {String key = entry.getKey();String value = entry.getValue();System.out.println(key + "=" + value);}System.out.println("--------------------------");}}

 超过10个使用copyOf()

//toArray方法在底层会比较集合的长度跟数组的长度两者的大小
        //如果集合的长度 > 数组的长度 :数据在数组中放不下,此时会根据实际数据的个数,重新创建数组
        //如果集合的长度 <= 数组的长度:数据在数组中放的下,此时不会创建新的数组,而是直接用

import java.util.HashMap;
import java.util.Map;public class ImmutableDemo4 {public static void main(String[] args) {/*创建Map的不可变集合,键值对的数量超过10个*///1.创建一个普通的Map集合HashMap<String, String> hm = new HashMap<>();hm.put("张三", "南京");hm.put("李四", "北京");hm.put("王五", "上海");hm.put("赵六", "北京");hm.put("孙七", "深圳");hm.put("周八", "杭州");hm.put("吴九", "宁波");hm.put("郑十", "苏州");hm.put("刘一", "无锡");hm.put("陈二", "嘉兴");hm.put("aaa", "111");//2.利用上面的数据来获取一个不可变的集合
/*//获取到所有的键值对对象(Entry对象)Set<Map.Entry<String, String>> entries = hm.entrySet();//把entries变成一个数组Map.Entry[] arr1 = new Map.Entry[0];//toArray方法在底层会比较集合的长度跟数组的长度两者的大小//如果集合的长度 > 数组的长度 :数据在数组中放不下,此时会根据实际数据的个数,重新创建数组//如果集合的长度 <= 数组的长度:数据在数组中放的下,此时不会创建新的数组,而是直接用Map.Entry[] arr2 = entries.toArray(arr1);//不可变的map集合Map map = Map.ofEntries(arr2);map.put("bbb","222");*///Map<Object, Object> map = Map.ofEntries(hm.entrySet().toArray(new Map.Entry[0]));Map<String, String> map = Map.copyOf(hm);map.put("bbb","222");}
}

3、小结

二、Stream流

Stream是Java 8 API添加的一个新的抽象,称为流Stream,以一种声明性方式处理数据集合(侧重对于源数据计算能力的封装,并且支持序列与并行两种操作方式)。流是个抽象的概念,是对输入输出设备的抽象,在Java程序中,对于数据的输入/输出操作都是以“流”的方式进行。

Stream流是从支持数据处理操作的源生成的元素序列,源可以是数组、文件、集合、函数。流不是集合元素,它不是数据结构并不保存数据,它的主要目的在于计算

Stream流是对集合(Collection)对象功能的增强,与Lambda表达式结合,可以提高编程效率、间接性和程序可读性。

1、体验Stream流的作用

普通代码:

  //1.把所有以“张”开头的元素存储到新集合中ArrayList<String> list2 = new ArrayList<>();for (String name : list1) {if(name.startsWith("张")){list2.add(name);}}//2.把“张”开头的,长度为3的元素再存储到新集合中ArrayList<String> list3 = new ArrayList<>();for (String name : list2) {if(name.length() == 3){list3.add(name);}}//3.遍历打印最终结果for (String name : list3) {System.out.println(name);}

 Stream流:

/*创建集合添加元素,完成以下需求:1.把所有以“张”开头的元素存储到新集合中2.把“张”开头的,长度为3的元素再存储到新集合中3.遍历打印最终结果*/ArrayList<String> list1 = new ArrayList<>();list1.add("张无忌");list1.add("周芷若");list1.add("赵敏");list1.add("张强");list1.add("张三丰");list1.stream().filter(name->name.startsWith("张")).filter(name->name.length()==3).forEach(name-> System.out.println(name));

2、Stream流的思想

3、Stream流的使用步骤

示例代码:

3.1、单列集合获取Stream流

//1.单列集合获取Stream流ArrayList<String> list = new ArrayList<>();Collections.addAll(list,"a","b","c","d","e");list.stream().forEach(s -> System.out.println(s));

该代码等于下面的一大堆

 //获取到一条流水线,并把集合中的数据放到流水线上Stream<String> stream1 = list.stream();//使用终结方法打印一下流水线上的所有数据stream1.forEach(new Consumer<String>() {@Overridepublic void accept(String s) {//s:依次表示流水线上的每一个数据System.out.println(s);}});

3.2、双列集合获取Stream流(先转成keySet()或entrySet())

需要先获取KeySet()/entrySet()转换成单列集合才能使用

public class StreamDemo3 {public static void main(String[] args) {//双列集合      无                                                   无法直接使用stream流//1.创建双列集合HashMap<String,Integer> hm = new HashMap<>();//2.添加数据hm.put("aaa",111);hm.put("bbb",222);hm.put("ccc",333);hm.put("ddd",444);//3.第一种获取stream流//hm.keySet().stream().forEach(s -> System.out.println(s));//4.第二种获取stream流hm.entrySet().stream().forEach(s-> System.out.println(s));}
}

3.3、数组获取Stream流(Arrays.stream())

//注意:
        //Stream接口中静态方法of的细节
        //方法的形参是一个可变参数,可以传递一堆零散的数据,也可以传递数组
        //但是数组必须是引用数据类型的,如果传递基本数据类型,是会把整个数组当做一个元素,放到Stream当中。

import java.util.stream.Stream;public class StreamDemo4 {public static void main(String[] args) {// 数组          public static <T> Stream<T> stream(T[] array)        Arrays工具类中的静态方法//1.创建数组int[] arr1 = {1,2,3,4,5,6,7,8,9,10};String[] arr2 = {"a","b","c"};//2.获取stream流// Arrays.stream(arr1).forEach(s-> System.out.println(s));//System.out.println("============================");//Arrays.stream(arr2).forEach(s-> System.out.println(s));//System.out.println("============================");//注意://Stream接口中静态方法of的细节//方法的形参是一个可变参数,可以传递一堆零散的数据,也可以传递数组//但是数组必须是引用数据类型的,如果传递基本数据类型,是会把整个数组当做一个元素,放到Stream当中。Stream.of(arr1).forEach(s-> System.out.println(s));//[I@41629346}
}

3.4、一堆零散数据(Stream.of())

//一堆零散数据   public static<T> Stream<T> of(T... values)           Stream接口中的静态方法Stream.of(1,2,3,4,5).forEach(s-> System.out.println(s));Stream.of("a","b","c","d","e").forEach(s-> System.out.println(s));

4、Stream流的中间方法

注意1:中间方法,返回新的Stream流,原来的Stream流只能使用一次,建议使用链式编程

注意2:修改Stream流中的数据,不会影响原来集合或者数组中的数据

4.1、filter方法(过滤)

package com.yaqi.a01mystream;import java.util.ArrayList;
import java.util.Collections;public class StreamDemo6 {public static void main(String[] args) {/*filter              过滤limit               获取前几个元素skip                跳过前几个元素注意1:中间方法,返回新的Stream流,原来的Stream流只能使用一次,建议使用链式编程注意2:修改Stream流中的数据,不会影响原来集合或者数组中的数据*/ArrayList<String> list = new ArrayList<>();Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰", "张翠山", "张良", "王二麻子", "谢广坤");//filter   过滤  把张开头的留下,其余数据过滤不要/*list.stream().filter(new Predicate<String>() {@Overridepublic boolean test(String s) {//如果返回值为true,表示当前数据留下//如果返回值为false,表示当前数据舍弃不要return s.startsWith("张");}}).forEach(s -> System.out.println(s));list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(s -> System.out.println(s));System.out.println("====================================");System.out.println(list);*//* limit               获取前几个元素skip                跳过前几个元素*///"张无忌", "周芷若", "赵敏", "张强", "张三丰", "张翠山", "张良", "王二麻子", "谢广坤"//list.stream().limit(3).forEach(s -> System.out.println(s));//list.stream().skip(4) .forEach(s -> System.out.println(s));//课堂练习://"张强", "张三丰", "张翠山"//第一种思路://先获取前面6个元素:"张无忌", "周芷若", "赵敏", "张强", "张三丰", "张翠山",//然后跳过前面3个元素//list.stream().limit(6).skip(3).forEach(s -> System.out.println(s));//第二种思路://先跳过3个元素:"张强", "张三丰", "张翠山", "张良", "王二麻子", "谢广坤"//然后再获取前面3个元素:"张强", "张三丰", "张翠山"//list.stream().skip(3).limit(3).forEach(s -> System.out.println(s));}
}

4.2、limit方法(获取前几个元素)

limit               获取前几个元素skip                跳过前几个元素*///"张无忌", "周芷若", "赵敏", "张强", "张三丰", "张翠山", "张良", "王二麻子", "谢广坤"//list.stream().limit(3).forEach(s -> System.out.println(s));//list.stream().skip(4) .forEach(s -> System.out.println(s));

4.3、skip方法(跳过前几个元素)

       list.stream().skip(4) .forEach(s -> System.out.println(s));

4.4 、练习

//课堂练习://"张强", "张三丰", "张翠山"//第一种思路://先获取前面6个元素:"张无忌", "周芷若", "赵敏", "张强", "张三丰", "张翠山",//然后跳过前面3个元素list.stream().limit(6).skip(3).forEach(s -> System.out.println(s));//第二种思路://先跳过3个元素:"张强", "张三丰", "张翠山", "张良", "王二麻子", "谢广坤"//然后再获取前面3个元素:"张强", "张三丰", "张翠山"list.stream().skip(3).limit(3).forEach(s -> System.out.println(s));

4.5、distinct方法(元素去重)

自定义JavaBean需要中间去重写hashCode和equals方法

ArrayList<String> list1 = new ArrayList<>();Collections.addAll(list1, "张无忌","张无忌","张无忌", "张强", "张三丰", "张翠山", "张良", "王二麻子", "谢广坤");ArrayList<String> list2 = new ArrayList<>();Collections.addAll(list2, "周芷若", "赵敏");// distinct            元素去重,依赖(hashCode和equals方法)list1.stream().distinct().forEach(s -> System.out.println(s));

4.6、concat方法(合并a和b两个流为一个流)

 Stream.concat(list1.stream(),list2.stream()).forEach(s -> System.out.println(s));

4.7、map方法(类型转换)

 ArrayList<String> list = new ArrayList<>();Collections.addAll(list, "张无忌-15", "周芷若-14", "赵敏-13", "张强-20", "张三丰-100", "张翠山-40", "张良-35", "王二麻子-37", "谢广坤-41");//需求:只获取里面的年龄并进行打印//String->int//第一个类型:流中原本的数据类型//第二个类型:要转成之后的类型//apply的形参s:依次表示流里面的每一个数据//返回值:表示转换之后的数据//当map方法执行完毕之后,流上的数据就变成了整数//所以在下面forEach当中,s依次表示流里面的每一个数据,这个数据现在就是整数了list.stream().map(new Function<String, Integer>() {@Overridepublic Integer apply(String s) {String[] arr = s.split("-");String ageString = arr[1];int age = Integer.parseInt(ageString);return age;}}).forEach(s-> System.out.println(s));System.out.println("------------------------");list.stream().map(s-> Integer.parseInt(s.split("-")[1])).forEach(s-> System.out.println(s));

5、Stream流的终结方法

5.1、forEach方法(遍历)

ArrayList<String> list = new ArrayList<>();Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰", "张翠山", "张良", "王二麻子", "谢广坤");//void forEach(Consumer action)           遍历//Consumer的泛型:表示流中数据的类型//accept方法的形参s:依次表示流里面的每一个数据//方法体:对每一个数据的处理操作(打印)/*list.stream().forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}});*/list.stream().forEach(s -> System.out.println(s));

5.2、count方法(统计)

 // long count()                            统计long count = list.stream().count();System.out.println(count);

5.3、toArray方法(收集流中的数据,放到数组中)

// toArray()                               收集流中的数据,放到数组中//Object[] arr1 = list.stream().toArray();//System.out.println(Arrays.toString(arr1));//IntFunction的泛型:具体类型的数组//apply的形参:流中数据的个数,要跟数组的长度保持一致//apply的返回值:具体类型的数组//方法体:就是创建数组//toArray方法的参数的作用:负责创建一个指定类型的数组//toArray方法的底层,会依次得到流里面的每一个数据,并把数据放到数组当中//toArray方法的返回值:是一个装着流里面所有数据的数组/* String[] arr = list.stream().toArray(new IntFunction<String[]>() {@Overridepublic String[] apply(int value) {return new String[value];}});System.out.println(Arrays.toString(arr));*/String[] arr2 = list.stream().toArray(value -> new String[value]);System.out.println(Arrays.toString(arr2));

5.4、collect方法(收集流中的数据,放到集合中)

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;public class StreamDemo10 {public static void main(String[] args) {/*collect(Collector collector)            收集流中的数据,放到集合中 (List Set Map)注意点:如果我们要收集到Map集合当中,键不能重复,否则会报错*/ArrayList<String> list = new ArrayList<>();Collections.addAll(list, "张无忌-男-15", "周芷若-女-14", "赵敏-女-13", "张强-男-20","张三丰-男-100", "张翠山-男-40", "张良-男-35", "王二麻子-男-37", "谢广坤-男-41");//收集List集合当中//需求://我要把所有的男性收集起来List<String> newList1 = list.stream().filter(s -> "男".equals(s.split("-")[1])).collect(Collectors.toList());//System.out.println(newList1);//收集Set集合当中//需求://我要把所有的男性收集起来Set<String> newList2 = list.stream().filter(s -> "男".equals(s.split("-")[1])).collect(Collectors.toSet());//System.out.println(newList2);//收集Map集合当中//谁作为键,谁作为值.//我要把所有的男性收集起来//键:姓名。 值:年龄Map<String, Integer> map = list.stream().filter(s -> "男".equals(s.split("-")[1]))/**   toMap : 参数一表示键的生成规则*           参数二表示值的生成规则** 参数一:*       Function泛型一:表示流中每一个数据的类型*               泛型二:表示Map集合中键的数据类型**        方法apply形参:依次表示流里面的每一个数据*               方法体:生成键的代码*               返回值:已经生成的键*** 参数二:*        Function泛型一:表示流中每一个数据的类型*                泛型二:表示Map集合中值的数据类型**       方法apply形参:依次表示流里面的每一个数据*               方法体:生成值的代码*               返回值:已经生成的值** */.collect(Collectors.toMap(new Function<String, String>() {@Overridepublic String apply(String s) {//张无忌-男-15return s.split("-")[0];}},new Function<String, Integer>() {@Overridepublic Integer apply(String s) {return Integer.parseInt(s.split("-")[2]);}}));Map<String, Integer> map2 = list.stream().filter(s -> "男".equals(s.split("-")[1])).collect(Collectors.toMap(s -> s.split("-")[0],s -> Integer.parseInt(s.split("-")[2])));System.out.println(map2);}

6、小结

三、方法引用

1、什么是方法引用?

方法引用就是把已经有的方法拿过来用,当做函数式接口中抽象方法的方法体

 函数式接口:FunctionInterface

1.1、示例代码

匿名内部类:

import java.util.Arrays;public class FunctionDemo1 {public static void main(String[] args) {//需求:创建一个数组,进行倒序排列Integer[] arr = {3, 5, 4, 1, 6, 2};//匿名内部类/* Arrays.sort(arr, new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return o2 - o1;}});*///lambda表达式//因为第二个参数的类型Comparator是一个函数式接口/* Arrays.sort(arr, (Integer o1, Integer o2)->{return o2 - o1;});*///lambda表达式简化格式//Arrays.sort(arr, (o1, o2)->o2 - o1 );//方法引用//1.引用处需要是函数式接口//2.被引用的方法需要已经存在//3.被引用方法的形参和返回值需要跟抽象方法的形参和返回值保持一致//4.被引用方法的功能需要满足当前的要求//表示引用FunctionDemo1类里面的subtraction方法//把这个方法当做抽象方法的方法体Arrays.sort(arr, FunctionDemo1::subtraction);System.out.println(Arrays.toString(arr));}//可以是Java已经写好的,也可以是一些第三方的工具类public static int subtraction(int num1, int num2) {return num2 - num1;}
}

1.2、小结

2、方法引用的分类

2.1、引用静态方法(类名::静态方法)

package com.yaqi.a01myfunction;import java.util.ArrayList;
import java.util.Collections;public class FunctionDemo2 {public static void main(String[] args) {/*方法引用(引用静态方法)格式类::方法名需求:集合中有以下数字,要求把他们都变成int类型"1","2","3","4","5"*///1.创建集合并添加元素ArrayList<String> list = new ArrayList<>();Collections.addAll(list,"1","2","3","4","5");//2.把他们都变成int类型/* list.stream().map(new Function<String, Integer>() {@Overridepublic Integer apply(String s) {int i = Integer.parseInt(s);return i;}}).forEach(s -> System.out.println(s));*///1.方法需要已经存在//2.方法的形参和返回值需要跟抽象方法的形参和返回值保持一致//3.方法的功能需要把形参的字符串转换成整数list.stream().map(Integer::parseInt).forEach(s-> System.out.println(s));}
}

 

2.2、引用成员方法(对象::成员方法)

方法引用(引用成员方法)
格式其他类:其他类对象::方法名本类:this::方法名(引用处不能是静态方法)父类:super::方法名(引用处不能是静态方法)

需求:集合中有一些名字,按照要求过滤数据数据:"张无忌","周芷若","赵敏","张强","张三丰"要求:只要以张开头,而且名字是3个字的

    //1.创建集合ArrayList<String> list = new ArrayList<>();//2.添加数据Collections.addAll(list,"张无忌","周芷若","赵敏","张强","张三丰");//3.过滤数据(只要以张开头,而且名字是3个字的)//list.stream().filter(s->s.startsWith("张")).filter(s->s.length() == 3).forEach(s-> System.out.println(s));/*  list.stream().filter(new Predicate<String>() {@Overridepublic boolean test(String s) {return s.startsWith("张") && s.length() == 3;}}).forEach(s-> System.out.println(s));*//*  StringOperation so = new StringOperation();list.stream().filter(so::stringJudge).forEach(s-> System.out.println(s));*///静态方法中是没有this的list.stream().filter(new FunctionDemo3()::stringJudge).forEach(s-> System.out.println(s));}public boolean stringJudge(String s){return s.startsWith("张") && s.length() == 3;}

App

package com.yaqi.a02game;public class App {public static void main(String[] args) {new LoginJFrame();}
}

 MyJFrame

package com.yaqi.a02game;import javax.swing.*;
import java.awt.event.ActionEvent;public class MyJFrame extends JFrame {public void method1(ActionEvent e) {System.out.println("go按钮被点击了");}
}

 LoginJFrame

package com.yaqi.a02game;import javax.swing.*;
import java.awt.*;public class LoginJFrame extends MyJFrame {JButton go = new JButton("Go");public LoginJFrame() {//设置图标setIconImage(Toolkit.getDefaultToolkit().getImage("myfunction\\image\\logo.jpg"));//设置界面initJframe();//添加组件initView();//界面显示出来this.setVisible(true);}//添加组件public void initView() {JLabel image = new JLabel(new ImageIcon("myfunction\\image\\kit.jpg"));image.setBounds(100,50,174,174);this.getContentPane().add(image);go.setFont(new Font(null,1,20));go.setBounds(120,274,150,50);go.setBackground(Color.WHITE);go.addActionListener(super::method1);this.getContentPane().add(go);}//设置界面public void initJframe() {//设置标题this.setTitle("随机点名器");//设置大小this.setSize(400, 500);//设置关闭模式this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置窗口无法进行调节this.setResizable(false);//界面居中this.setLocationRelativeTo(null);//取消内部默认居中放置this.setLayout(null);//设置背景颜色this.getContentPane().setBackground(Color.white);this.setAlwaysOnTop(true);//置顶}}

 本类:this::方法名(引用处不能是静态方法)

父类:super::方法名(引用处不能是静态方法)

2.3、引用构造方法(类名::new)

package com.yaqi.a01myfunction;import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;public class FunctionDemo4 {public static void main(String[] args) {/*方法引用(引用构造方法)格式类名::new目的:创建这个类的对象需求:集合里面存储姓名和年龄,要求封装成Student对象并收集到List集合中方法引用的规则:1.需要有函数式接口2.被引用的方法必须已经存在3.被引用方法的形参和返回值,需要跟抽象方法的形参返回值保持一致4.被引用方法的功能需要满足当前的需求*///1.创建集合对象ArrayList<String> list = new ArrayList<>();//2.添加数据Collections.addAll(list, "张无忌,15", "周芷若,14", "赵敏,13", "张强,20", "张三丰,100", "张翠山,40", "张良,35", "王二麻子,37", "谢广坤,41");//3.封装成Student对象并收集到List集合中//String --> Student/*  List<Student> newList = list.stream().map(new Function<String, Student>() {@Overridepublic Student apply(String s) {String[] arr = s.split(",");String name = arr[0];int age = Integer.parseInt(arr[1]);return new Student(name, age);}}).collect(Collectors.toList());System.out.println(newList);*/List<Student> newList2 = list.stream().map(Student::new).collect(Collectors.toList());System.out.println(newList2);}
}

只需要保证构造方法结束后生成的对象与抽象方法的返回值保持一致就可以了 

 

 

2.4、其它调用方式(Ⅰ. 使用类名引用成员方法 Ⅱ. 引用数组的构造方法)

2.4.1 使用类名引用成员方法

package com.yaqi.a01myfunction;import java.util.ArrayList;
import java.util.Collections;public class FunctionDemo5 {public static void main(String[] args) {/*方法引用(类名引用成员方法)格式类名::成员方法需求:集合里面一些字符串,要求变成大写后进行输出*///1.创建集合对象ArrayList<String> list = new ArrayList<>();//2.添加数据Collections.addAll(list, "aaa", "bbb", "ccc", "ddd");//3.变成大写后进行输出//map(String::toUpperCase)//拿着流里面的每一个数据,去调用String类中的toUpperCase方法,方法的返回值就是转换之后的结果。list.stream().map(String::toUpperCase).forEach(s -> System.out.println(s));//String --> String/* list.stream().map(new Function<String, String>() {@Overridepublic String apply(String s) {return s.toUpperCase();}}).forEach(s -> System.out.println(s));*/}
}

方法引用的规则:
        1.需要有函数式接口
        2.被引用的方法必须已经存在
        3.被引用方法的形参,需要跟抽象方法的第二个形参到最后一个形参保持一致,返回值需要保持一致。
        4.被引用方法的功能需要满足当前的需求

        抽象方法形参的详解:
        第一个参数:表示被引用方法的调用者,决定了可以引用哪些类中的方法
                    在Stream流当中,第一个参数一般都表示流里面的每一个数据。
                    假设流里面的数据是字符串,那么使用这种方式进行方法引用,只能引用String这个类中的方法

        第二个参数到最后一个参数:跟被引用方法的形参保持一致,如果没有第二个参数,说明被引用的方法需要是无参的成员方法

        局限性
            不能引用所有类中的成员方法。
            是跟抽象方法的第一个参数有关,这个参数是什么类型的,那么就只能引用这个类中的方法。

参数类型必须相同

2.4.2引用数组的构造方法 


 

细节: 数组的类型,需要跟流中数据的类型保持一致。 

package com.yaqi.a01myfunction;import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;public class FunctionDemo6 {public static void main(String[] args) {/*方法引用(数组的构造方法)格式数据类型[]::new目的:创建一个指定类型的数组需求:集合中存储一些整数,收集到数组当中细节:数组的类型,需要跟流中数据的类型保持一致。*///1.创建集合并添加元素ArrayList<Integer> list = new ArrayList<>();Collections.addAll(list, 1, 2, 3, 4, 5);//2.收集到数组当中Integer[] arr2 = list.stream().toArray(Integer[]::new);System.out.println(Arrays.toString(arr2));/*Integer[] arr = list.stream().toArray(new IntFunction<Integer[]>() {@Overridepublic Integer[] apply(int value) {return new Integer[value];}});*///3.打印}
}

3、小结

4、方法引用综合小练习

①、练习1

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;public class FunctionDemo7 {public static void main(String[] args) {/*需求:集合中存储一些字符串的数据,比如:张三,23。收集到Student类型的数组当中*///1.创建集合并添加元素ArrayList<String> list = new ArrayList<>();Collections.addAll(list, "张无忌,15", "周芷若,14", "赵敏,13", "张强,20", "张三丰,100", "张翠山,40", "张良,35", "王二麻子,37", "谢广坤,41");//2.先把字符串变成Student对象,然后再把Student对象收集起来Student[] arr = list.stream().map(Student::new).toArray(Student[]::new);//打印数组System.out.println(Arrays.toString(arr));}
}

②、练习 2

技巧:
*       1.现在有没有一个方法符合我当前的需求
*       2.如果有这样的方法,这个方法是否满足引用的规则
*       静态   类名::方法名
*       成员方法
*       构造方法  类名::new
 //1.创建集合ArrayList<Student> list = new ArrayList<>();//2.添加元素list.add(new Student("zhangsan",23));list.add(new Student("lisi",24));list.add(new Student("wangwu",25));//3.获取姓名并放到数组当中String[] arr = list.stream().map(Student::getName).toArray(String[]::new);/* String[] arr = list.stream().map(new Function<Student, String>() {@Overridepublic String apply(Student student) {return student.getName();}}).toArray(String[]::new);*/System.out.println(Arrays.toString(arr));

③、练习3

相当于练习1和练习2的结合:(在Student.java中新增了一个方法getNameAge,用以返回对应格式的字符串) 

public String getNameAge(){return name+'-'+age;}
ArrayList<Student> list = new ArrayList<>();list.add(new Student("zhangsan",23));list.add(new Student("lisi",24));list.add(new Student("wangwu",25));String[] array = list.stream().map(Student::getNameAge).toArray(String[]::new);System.out.println(Arrays.toString(array));

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/257694.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Duilib List 控件学习

这是自带的一个示例; 一开始运行的时候List中是空的,点击Search按钮以后就填充列表框; 先看一下列表框列头是在xml文件中形成的; <List name="domainlist" bkcolor="#FFFFFFFF" ... menu="true"> <ListHeader height="24…

2048游戏C++板来啦!

个人主页&#xff1a;PingdiGuo_guo 收录专栏&#xff1a;C干货专栏 大家好呀&#xff0c;我是PingdiGuo_guo&#xff0c;今天我们来学习如何用C编写一个2048小游戏。 文章目录 1.2048的规则 2.步骤实现 2.1: 初始化游戏界面 2.1.1知识点 2.1.2: 创建游戏界面 2.2: 随机…

Leetcode 236.二叉树的最近公共祖先

题目描述 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个节点 p、q&#xff0c;最近公共祖先表示为一个节点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&#xff08;一个节点也可以是它自己的…

【sgSearch】自定义组件:常用搜索栏筛选框组件(包括表格高度变化兼容)。

sgSearch源码 <template><div :class"$options.name" :expand"expandSearch" :showCollapseBtn"showCollapseBtn"><!-- v-clickoutside"(d) > (expandSearch false)" --><ul class"search-list"&…

深度学习从入门到不想放弃-7

上一章的内容 深度学习从入门到不想放弃-6 (qq.com) 今天讲的也算基础(这个系列后来我一寻思,全是基础 ),但是可能要着重说下,今天讲前向计算和反向传播,在哪儿它都永远是核心,不管面对什么模型 前向计算: 有的叫也叫正向传播,正向计算的,有的直接把前向的方法梯度下…

解决 postman测试接口报404 Not Found

JDK版本&#xff1a;jdk17 IDEA版本&#xff1a;IntelliJ IDEA 2022.1.3 文章目录 问题描述原因分析解决方案 问题描述 当我使用postman测试接口时&#xff0c;报了 404 Not Found 的错误&#xff0c;报错截图如下所示 但我的后端程序中已经定义了该接口&#xff0c;如下所示 …

代码随想录算法训练营第三十一天 |基础知识,455.分发饼干,376.摆动序列,53.最大子序和(已补充)

基础知识&#xff1a; 题目分类大纲如下&#xff1a; #算法公开课 《代码随想录》算法视频公开课(opens new window)&#xff1a;贪心算法理论基础&#xff01;(opens new window),相信结合视频再看本篇题解&#xff0c;更有助于大家对本题的理解。 #什么是贪心 贪心的本质…

第一篇【传奇开心果系列】Python的pyttsx3库技术点案例示例:文本转换语言

传奇开心果短博文系列 系列短博文目录Python的pyttsx3库技术点案例示例系列 短博文目录前言一、pyttsx3主要特点和功能介绍二、pyttsx3文字转语音操作步骤介绍三、多平台支持介绍和示例代码四、多语言支持介绍和示例代码五、自定义语言引擎介绍和示例代码六、调整语速和音量介绍…

【Mybatis】从0学习Mybatis(2)

前言 本篇文章是从0学习Mybatis的第一篇文章&#xff0c;由于篇幅太长CSDN会限流&#xff0c;因此我打算分开两期来写&#xff0c;这是第二期&#xff01;第一期在这儿&#xff1a;【Mybatis】从0学习Mybatis&#xff08;1&#xff09;-CSDN博客 1.什么是ResultMap结果映射&am…

【教程】C++语言基础学习笔记(七)——Array数组

写在前面&#xff1a; 如果文章对你有帮助&#xff0c;记得点赞关注加收藏一波&#xff0c;利于以后需要的时候复习&#xff0c;多谢支持&#xff01; 【C语言基础学习】系列文章 第一章 《项目与程序结构》 第二章 《数据类型》 第三章 《运算符》 第四章 《流程控制》 第五章…

蓝桥杯第十四届电子类单片机组程序设计

目录 前言 蓝桥杯大赛历届真题&#xff08;点击查看&#xff09; 一、第十四届比赛题目 1.比赛原题 2.题目解读 1&#xff09;任务要求 2&#xff09;注意事项 二、任务实现 1.NE555读取时机的问题 1&#xff09;缩短计数时间 2&#xff09;实时读取 2.温度传感器读…

机器学习和统计学的区别?

1、本质区别&#xff1a; 目标&#xff1a;机器学习的核心目标是建立一个可以自动学习和改进的模型&#xff0c;以预测未知数据。它更关注结果的准确性和模型的泛化能力&#xff0c;通常不关心模型是否可以解释。而统计学的目标是探究变量之间的关系&#xff0c;理解数据的内在…

算法沉淀——队列+宽度优先搜索(BFS)(leetcode真题剖析)

算法沉淀——队列宽度优先搜索&#xff08;BFS&#xff09; 01.N 叉树的层序遍历02.二叉树的锯齿形层序遍历03.二叉树最大宽度04.在每个树行中找最大值 队列 宽度优先搜索算法&#xff08;Queue BFS&#xff09;是一种常用于图的遍历的算法&#xff0c;特别适用于求解最短路径…

知识价值2-什么是IDE?新手用哪个IDE比较好?

IDE是集成开发环境&#xff08;Integrated Development Environment&#xff09;的缩写&#xff0c;是一种软件应用程序&#xff0c;旨在提供集成的工具集&#xff0c;以方便开发人员进行软件开发。IDE通常包括代码编辑器、编译器、调试器和其他工具&#xff0c;以支持软件开发…

python+django+vue汽车票在线预订系统58ip7

本课题使用Python语言进行开发。基于web,代码层面的操作主要在PyCharm中进行&#xff0c;将系统所使用到的表以及数据存储到MySQL数据库中 使用说明 使用Navicat或者其它工具&#xff0c;在mysql中创建对应名称的数据库&#xff0c;并导入项目的sql文件&#xff1b; 使用PyChar…

PHP开发日志 ━━ 深入理解三元操作与一般条件语句的不同

概况 三元运算符的功能与“if…else”流程语句一致。 在一般情况下&#xff0c;三元操作替换if条件语句可以精简代码&#xff0c;并且更为直观&#xff0c;但是在下面的情况中使用三元操作将会返回警告。 借图&#xff1a; 案例 比如原代码&#xff1a; class classA{publ…

详解tomcat中的jmx监控

目录 1.概述 2.如何开启tomcat的JMX 3.tomcat如何实现JMX的源码分析 1.概述 本文是博主JAVA监控技术系列文章的第二篇&#xff0c;前面一篇文章中我们介绍了JAVA监控技术的基石——jmx&#xff1a; 【JMX】JAVA监控的基石-CSDN博客 本文我们将从使用和源码实现两个方面聊…

算法学习——LeetCode力扣回溯篇3

算法学习——LeetCode力扣回溯篇3 491. 非递减子序列 491. 非递减子序列 - 力扣&#xff08;LeetCode&#xff09; 描述 给你一个整数数组 nums &#xff0c;找出并返回所有该数组中不同的递增子序列&#xff0c;递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。…

android 控制台输出 缺失

问题 android 控制台输出内容缺失 详细问题 笔者进行android开发&#xff0c;期望控制台打印Log日志或是输出内容 Log.i("tag","content");或 System.out.println("content")但是实际上&#xff0c;上述内容并没有按照笔者期望打印 解决方…