黑马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.mzph.cn/news/682721.shtml

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

相关文章

站在C/C++的肩膀速通Java面向对象

默认学过C或C&#xff0c;对变量、表达式、选择、循环都会。 运行特征 解释型语言&#xff08;JavaScript、Python等&#xff09; 源文件-(平台专属解释器)->解释器中执行编译型语言&#xff08;C、Go等&#xff09; 源文件-(平台编译器)->平台可执行文件Java 源文件-(…

【白话前端】JS库的作用和常见的九种类型—值得收藏

js库就好比预制菜&#xff0c;我们想吃美食没必要从买菜、择菜、炒菜开始&#xff0c;直接加工就行。 一、什么是JS库 JS库&#xff08;JavaScript Library&#xff09;是指一组封装好的函数、方法、类等&#xff0c;用于简化开发者的编程工作。它们通常提供了常用的功能和算…

Android ·移动应用开发 创建第一个Android项目

文章目录 一、创建第一个Android项目1.1 准备好Android Studio1.2 运行程序1.3 程序结构是什么app下的结构res - 子目录&#xff08;所有图片、布局、字符串等资源&#xff09;AndroidManifest.xml 有四大组件&#xff0c;程序添加权限声明 Project下的结构 二、开发android时&…

【ArcGIS Pro二次开发】(79):符号系统_CIMUniqueValueRenderer

CIMUniqueValueRenderer是ArcGIS Pro SDK中的一个类&#xff0c;用于创建唯一值渲染器&#xff08;Unique Value Renderer&#xff09;。 在ArcGIS Pro中长这样&#xff1a; 通过对CIMUniqueValueRenderer的操作&#xff0c;可以对符号系统进行更改&#xff0c;实现很多功能。…

尚硅谷最新Node.js 学习笔记(一)

目录 一、Nodejs入门 1.1、为什么要学习Nodejs&#xff1f; 1.2、Nodejs是什么&#xff1f; 1.3、Nodejs的作用 1.4、Nodejs安装 1.5、Nodejs初体验 1.6、编码注意事项 二、Buffer&#xff08;缓冲器&#xff09; 2.1、概念 2.2、特点 2.3、使用 创建Buffer Buffe…

Cocos2dx-lua ScrollView[一]基础篇

一.ScrollView概述 cocos游戏中ScrollView控件大量使用,95%以上的项目都会使用ScrollView,个别游戏可能全部使用翻页的滑动效果。如果想要精通Cocos的UI开发,精通ScrollView控件非常关键,因此对ScrollView的使用进行总结很有必要。 下文缩写说明:sv = ScrollView, item代…

嵌入式Linux网络编程入门:轻松构建网络通信

大家好&#xff0c;今天给大家介绍嵌入式Linux网络编程入门&#xff1a;轻松构建网络通信&#xff0c;文章末尾附有分享大家一个资料包&#xff0c;差不多150多G。里面学习内容、面经、项目都比较新也比较全&#xff01;可进群免费领取。 为什么选择嵌入式Linux网络编程&#x…

vue3+ts+vite+uniapp项目常见问题

vue3tsvite中""路径失效的问题 ""需要进行配置&#xff1a; 首先npm install types/node --save-dev&#xff08;需要用到node其中的path&#xff09;接着在vite.config.ts配置文件中进行配置&#xff1a; 引入 import path from ‘path’&#xff0c;然…

Imgui(2) | macOS 绘制 CPU 占用率曲线

Imgui(2) | macOS 绘制 CPU 占用率曲线 文章目录 Imgui(2) | macOS 绘制 CPU 占用率曲线0. 简介1. 绘制曲线 - 以正弦函数为例1.1 基于 sf::RectangleShape 的渲染 - 不好看&#xff0c;效率低1.2 基于 sf::VertexArray 的绘制 2. 获取和绘制所有 CPU 的占用率2.1 测试程序 - 用…

LeetCode Python - 16.最接近的三数之和

目录 题目答案运行结果 题目 给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数&#xff0c;使它们的和与 target 最接近。 返回这三个数的和。 假定每组输入只存在恰好一个解。 示例 1&#xff1a; 输入&#xff1a;nums [-1,2,1,-4],…

基于轻量级卷积神经网络模型MobileNet开发构建基于GTSRB数据集的道路交通标识识别系统

相信经常需要开车出行的人对于各种各样的道路交通标识定是不陌生的&#xff0c;但是对于经常不开车的人来说生活中出现的形形色色的道路交通标识就未必都能认出来了&#xff0c;本文的主要目的就是想要基于CNN来开发构建道路交通标识识别分析系统&#xff0c;实现看图识标&…

谷歌浏览器安装扩展程序axure-chrome-extension

注&#xff1a; 文末附扩展附件&#xff1a;axure-chrome-extension_v0.7.0.crx 1、安装扩展程序axure-chrome-extension 找到axure-chrome-extension.crx&#xff0c;把axure-chrome-extension.crx后缀改为zip&#xff0c;然后解压&#xff0c;得到一个文件夹 2、打开谷歌浏览…

枚举知识点解析

枚举是什么&#xff1f;枚举就是列举&#xff0c; 将东西一一列举出来。 生活中有许多地方需要用到枚举&#xff0c; 比如一年有12个月&#xff0c;一星期有7天&#xff0c; 这些都需要进行枚举。 那么&#xff0c; 如何进行枚举的定义呢&#xff1f; 如下 枚举中的值是一种…

ubuntu22.04@laptop OpenCV Get Started: 008_image_filtering_using_convolution

ubuntu22.04laptop OpenCV Get Started: 008_image_filtering_using_convolution 1. 源由2. convolution应用Demo2.1 C应用Demo2.2 Python应用Demo 3. 重点分析3.1 identity矩阵3.2 all ones 5x5矩阵3.3 blur 5x5矩阵3.4 GaussianBlur 5x5矩阵3.5 medianBlur 5x5矩阵3.6 Sharpe…

Spring 用法学习总结(一)之基于 XML 注入属性

百度网盘&#xff1a; &#x1f449; Spring学习书籍链接 Spring学习 1 Spring框架概述2 Spring容器3 基于XML方式创建对象4 基于XML方式注入属性4.1 通过set方法注入属性4.2 通过构造器注入属性4.3 使用p命名空间注入属性4.4 注入bean与自动装配4.5 注入集合4.6 注入外部属性…

C# Winform .net6自绘的圆形进度条

using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms;namespace Net6_GeneralUiWinFrm {public class CircularProgressBar : Control{private int progress 0;private int borderWidth 20; // 增加的边框宽度public int Progr…

CTFshow web(php文件上传155-158)

web155 老样子&#xff0c;还是那个后端检测。 知识点&#xff1a; auto_append_file 是 PHP 配置选项之一&#xff0c;在 PHP 脚本执行结束后自动追加执行指定的文件。 当 auto_append_file 配置被设置为一个文件路径时&#xff0c;PHP 将在执行完脚本文件的所有代码后&…

探索IDE的世界:什么是IDE?以及适合新手的IDE推荐

引言 在编程的世界里&#xff0c;集成开发环境&#xff08;IDE&#xff09;是我们日常工作的重要工具。无论是初学者还是经验丰富的开发者&#xff0c;一个好的IDE都能极大地提高我们的编程效率。那么&#xff0c;什么是IDE呢&#xff1f;对于新手来说&#xff0c;又应该选择哪…

OpenGL-ES 学习(2)---- DepthTest

深度测试 OpenGL-ES 深度测试是指在片段着色器执行之后&#xff0c;利用深度缓冲区所保存的深度值决定当前片段是否被丢弃的过程 深度缓冲区通常和颜色缓冲区有着相同的宽度和高度&#xff0c;一般由窗口系统自动创建并将其深度值存储为 16、 24 或 32 位浮点数。(注意只保存…

红队笔记Day3-->隧道上线不出网机器

昨天讲了通过代理的形式&#xff08;端口转发&#xff09;实现了上线不出网的机器&#xff0c;那么今天就来讲一下如何通过隧道上线不出网机器 目录 1.网络拓扑 2.开始做隧道&#xff1f;No&#xff01;&#xff01;&#xff01; 3.icmp隧道 4.HTTP隧道 5.SSH隧道 1.什么…