Stream流和方法引用

不可变集合

不可变集合是一个长度不可变,内容也无法修改的集合

使用场景

如果某个数据不能被修改,把它防御性地拷贝到不可变集合中是个很好的实践。

当集合对象被不可信的库调用时,不可变形式是安全的。

简单理解:

​不想让别人修改集合中的内容

比如说:

1,斗地主的54张牌,是不能添加,不能删除,不能修改的

2,斗地主的打牌规则:单张,对子,三张,顺子等,也是不能修改的

3,用代码获取的操作系统硬件信息,也是不能被修改的

不可变集合分类

  • 不可变的list集合
public class ListDemo {
    public static void main(String[] args) {
        List<String> list = List.of("张三", "李四", "王五", "赵六");

        Iterator<String> it = list.iterator();
        while (it.hasNext()){
            String s = it.next();
            System.out.println(s);
        }

        //list.remove("张三");//UnsupportedOperationException
        //list.add("qx");//UnsupportedOperationException
        list.set(0,"fzx");//UnsupportedOperationException
    }
}
  • 不可变的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("王五");//UnsupportedOperationException
    }
}
  • 不可变的map集合
public class MapDemo {
    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);
        }

        map.put("fzx","qx");//UnsupportedOperationException
    }
}

键值对个数大于10

public class ImmutableMapDemo {
    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("fzx", "深圳");

        //获取到所有的键值对对象(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 map1 = Map.ofEntries(arr2);
        //map1.put("qixuan","杭州");//UnsupportedOperationException

        Map<Object, Object> map2 = Map.ofEntries(entries.toArray(new Map.Entry[0]));

        //JDK10之后的方法,底层原理跟上面的一样
        Map<String, String> map3 = Map.copyOf(hm);

        map3.put("qixuan","杭州");//UnsupportedOperationException

    }
}

Stream流

体验Stream流

  • 案例需求

    按照下面的要求完成集合的创建和遍历

    • 创建一个集合,存储多个字符串元素
    • 把集合中所有以"张"开头的元素存储到一个新的集合
    • 把"张"开头的集合中的长度为3的元素存储到一个新的集合
    • 遍历上一步得到的集合
  • 原始方式示例代码

    public static void main(String[] args) {
        //集合的批量添加
        ArrayList<String> list1 = new ArrayList<>(List.of("张sf","张wj","张cs","王hh","张l","谢gk"));

        //遍历list1把以张开头的元素添加到list2中。
        ArrayList<String> list2 = new ArrayList<>();
        for (String s : list1) {
            if(s.startsWith("张")){
                list2.add(s);
            }
        }
        ArrayList<String> list3 = new ArrayList<>();
        //遍历list2集合,把其中长度为3的元素,再添加到list3中
        for (String s : list2) {
            if(s.length() == 3){
                list3.add(s);
            }
        }
        for (String s : list3) {
            System.out.println(s);
        }
    }
}
  • 使用Stream流示例代码
public class Test {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>(List.of("张sf","张wj","张cs","王hh","张l","谢gk"));

        //Stream流
        list.stream().filter(s->s.startsWith("张"))
                .filter(s->s.length() == 3)
                .forEach(s -> System.out.println(s));
    }
}
  • Stream流的好处
    • 直接阅读代码的字面意思即可完美展示无关逻辑方式的语义:获取流、过滤姓张、过滤长度为3、逐一打印
    • Stream流把真正的函数式编程风格引入到Java中
    • 代码简洁

Stream流的常见生成方式

  • Stream流的三类方法
    • 获取Stream流
      • 创建一条流水线,并把数据放到流水线上准备进行操作
    • 中间方法
      • 流水线上的操作
      • 一次操作完毕之后,还可以继续进行其他操作
    • 终结方法
      • 一个Stream流只能有一个终结方法
      • 是流水线上的最后一个操作
  • 生成Stream流的方式
    • Collection体系集合

      使用默认方法stream()生成流, default Stream < E > stream()

    • Map体系集合

      把Map转成Set集合,间接的生成流

    • 数组

      通过Arrays中的静态方法stream生成流

    • 同种数据类型的多个数据

      通过Stream接口的静态方法of(T… values)生成流

public class StreamDemo {
   public static void main(String[] args) {
       //Collection体系的集合可以使用默认方法stream()生成流
       List<String> list = new ArrayList<>();
       Stream<String> listStream = list.stream();

       Set<String> set = new HashSet<>();
       Stream<String> setStream = set.stream();

       //Map体系的集合间接的生成流
       Map<String,Integer> map = new HashMap<>();
       Stream<String> keyStream = map.keySet().stream();
       Stream<Integer> valueStream = map.values().stream();
       Stream<Map.Entry<String, Integer>> entryStream = map.entrySet().stream();

       //数组可以通过Arrays中的静态方法stream生成流
       String[] strArray = {};
       Stream<String> strStream = Arrays.stream(strArray);

       //同种数据类型的多个数据可以通过Stream接口的静态方法of(T... values)生成流
       Stream<String> stringStream = Stream.of("fzx", "qiqi", "zx");
       Stream<Integer> integerStream = Stream.of(10, 20, 25);
   }
}

Stream流中间操作方法

  • 概念
    中间操作的意思是,执行完此方法之后,Stream流依然可以继续执行其他操作
  • 常见方法
Stream<T> filter(Predicate predicate)	用于对流中的数据进行过滤
Stream<T> limit(long maxSize)	返回此流中的元素组成的流,截取前指定参数个数的数据
Stream<T> skip(long n)	跳过指定参数个数的数据,返回由该流的剩余元素组成的流
static <T> Stream<T> concat(Stream a, Stream b)	合并a和b两个流为一个流
Stream<T> distinct()	返回由该流的不同元素(根据Object.equals(Object) )组成的流
  • filter代码演示
public class StreamFifterDemo {
    public static void main(String[] args) {
        //Stream<T> filter(Predicate predicate):过滤
        //Predicate接口中的方法	boolean test(T t):对给定的参数进行判断,返回一个布尔值
        ArrayList<String> list = new ArrayList<>();
        list.add("张sf");
        list.add("张wj");
        list.add("张cs");
        list.add("王hh");
        list.add("张l");
        list.add("谢gk");

        //filter方法获取流中的 每一个数据.
        //而test方法中的s,就依次表示流中的每一个数据.
        //我们只要在test方法中对s进行判断就可以了.
        //如果判断的结果为true,则当前的数据留下.
        //如果判断的结果为false,则当前数据就不要.
        
        /*list.stream().filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.startsWith("张");
            }
        }).forEach(s -> System.out.println(s));*/

        //因为Predicate接口中只有一个抽象方法test
        //所以我们可以使用lambda表达式来简化
        list.stream().filter(s-> s.startsWith("张")).forEach(s -> System.out.println(s));
    }
}
  • limit&skip代码演示
public class StreamMain {
    public static void main(String[] args) {
        //创建一个集合,存储多个字符串元素
        ArrayList<String> list = new ArrayList<String>();

        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        list.add("ddd");
        list.add("eee");
        list.add("fff");

        //需求1:取前3个数据在控制台输出
        list.stream().limit(4).forEach(s -> System.out.print(s+" "));
        System.out.println();

        //需求2:跳过3个元素,把剩下的元素在控制台输出
        list.stream().skip(3).forEach(s -> System.out.print(s+" "));
        System.out.println();

        //需求3:跳过2个元素,把剩下的元素中前2个在控制台输出
        list.stream().skip(2).limit(2).forEach(s -> System.out.print(s+" "));
    }
}
  • concat&distinct代码演示
public class StreamTest {
    public static void main(String[] args) {
        //创建一个集合,存储多个字符串元素
        ArrayList<String> list = new ArrayList<String>();

        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        list.add("ddd");
        list.add("eee");
        list.add("fff");

        //需求1:取前4个数据组成一个流
        Stream<String> s1 = list.stream().limit(4);

        //需求2:跳过2个数据组成一个流
        Stream<String> s2 = list.stream().skip(2);

        //需求3:合并需求1和需求2得到的流,并把结果在控制台输出
        /*Stream.concat(s1,s2).forEach(s -> System.out.print(s+" "));
        System.out.println();*/

        //需求4:合并需求1和需求2得到的流,并把结果在控制台输出,要求字符串元素不能重复
        Stream.concat(s1,s2).distinct().forEach(s -> System.out.print(s+" "));
    }
}

Stream流终结操作方法

  • 概念
    • 终结操作的意思是:执行完此方法之后,Stream流将不能再执行其他操作
  • 常见方法
void forEach(Consumer action)	对此流的每个元素执行操作
long count()	返回此流中的元素数
  • 代码演示
public class EndStream {
    public static void main(String[] args) {
        //创建一个集合,存储多个字符串元素
        ArrayList<String> list = new ArrayList<String>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        list.add("ddd");
        list.add("eee");
        list.add("fff");
        
        method(list);

        //long count():返回此流中的元素数
        long count = list.stream().count();
        System.out.println(count);
    }
    public static void method(ArrayList<String> list){
        //  void forEach(Consumer action):对此流的每个元素执行操作
        //  Consumer接口中的方法void accept(T t):对给定的参数执行此操作
        //在forEach方法的底层,会循环获取到流中的每一个数据.
        //并循环调用accept方法,并把每一个数据传递给accept方法
        //s就依次表示了流中的每一个数据.
        list.stream().forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.print(s + " ");
            }
        });
        System.out.println();
        System.out.println("---------------------");
        //lambda表达式的简化格式
        //是因为Consumer接口中,只有一个accept方法,即是函数式接口
        list.stream().forEach(s-> System.out.print(s+" "));
    }
}

Stream流的收集操作

  • 概念
    对数据使用Stream流的方式操作完毕后,可以把流中的数据收集到集合中
  • 常用方法
R collect(Collector collector)	把结果收集到集合中
  • 工具类Collectors提供了具体的收集方式
public static <T> Collector toList()	把元素收集到List集合中
public static <T> Collector toSet()		把元素收集到Set集合中
public static Collector toMap(Function keyMapper,Function valueMapper)	把元素收集到Map集合中
  • 代码示例
public class MyStream {
    public static void main(String[] args) {
        ArrayList<Integer> list1 = new ArrayList<>();
        for (int i = 1; i <= 10; i++) {
            list1.add(i);
        }

        list1.add(10);
        list1.add(10);
        list1.add(10);
        list1.add(10);
        list1.add(10);

        //filter负责过滤数据的.
        //collect负责收集数据.
        //获取流中剩余的数据,但是他不负责创建容器,也不负责把数据添加到容器中.
        //Collectors.toList() : 在底层会创建一个List集合.并把所有的数据添加到List集合中.
        List<Integer> list = list1.stream().filter(number -> number % 2 == 0)
                .collect(Collectors.toList());
        System.out.println(list);

        //set集合中元素不可重复
        Set<Integer> set = list1.stream().filter(number -> number % 2 == 0)
                .collect(Collectors.toSet());
        System.out.println(set);
    }
}
public class MyStreamDemo {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("fzx,20");
        list.add("xuanxuan,25");
        list.add("qiqi,23");

        Map<String, String> map = list.stream().filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                String[] split = s.split(",");
                int age = Integer.parseInt(split[1]);
                return age >= 24;
            }
        }).collect(Collectors.toMap(
                s -> s.split(",")[0],
                s -> s.split(",")[1]
        ));
        System.out.println(map);
    }
}

Stream流综合练习

  • 案例需求
    现在有两个ArrayList集合,分别存储6名男演员名称和6名女演员名称,要求完成如下的操作

    • 男演员只要名字为3个字的前三人
    • 女演员只要姓林的,并且不要第一个
    • 把过滤后的男演员姓名和女演员姓名合并到一起
    • 把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据

演员类Actor已经提供,里面有一个成员变量,一个带参构造方法,以及成员变量对应的get/set方法
代码实现

public class Main {
    public static void main(String[] args) {
        //创建集合
        ArrayList<String> manList = new ArrayList<String>();
        manList.add("周润发");
        manList.add("成龙");
        manList.add("刘德华");
        manList.add("吴京");
        manList.add("周星驰");
        manList.add("李连杰");

        ArrayList<String> womanList = new ArrayList<String>();
        womanList.add("林心如");
        womanList.add("张曼玉");
        womanList.add("林青霞");
        womanList.add("柳岩");
        womanList.add("林志玲");
        womanList.add("王祖贤");

        //男演员只要名字为3个字的前三人
        Stream<String> manStream = manList.stream().filter(s -> s.length() == 3).limit(3);

        //女演员只要姓林的,并且不要第一个
        Stream<String> womanStream = womanList.stream().filter(s -> s.startsWith("林")).skip(1);

        //把过滤后的男演员姓名和女演员姓名合并到一起
        Stream<String> concatStream = Stream.concat(manStream, womanStream);

        // 将流中的数据封装成Actor对象之后打印
        concatStream.forEach(s-> {
                Actor actor = new Actor(s);
                System.out.println(actor.getName());
            });
    }
}
class Actor {
    private String name;

    public Actor(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

方法引用

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

  • 引用处必须是函数式接口
  • 被引用的方法必须已经存在
  • 被引用方法的形参和返回值需要跟抽象方法一致
  • 被引用方法的功能要满足当前需求

体验方法引用

  • 方法引用的出现原因

    • 在使用Lambda表达式的时候,我们实际上传递进去的代码就是一种解决方案:拿参数做操作
    • 那么考虑一种情况:如果我们在Lambda中所指定的操作方案,已经有地方存在相同方案,那是否还有必要再写重复逻辑呢?答案肯定是没有必要
    • 那我们又是如何使用已经存在的方案的呢?
    • 这就是我们要讲解的方法引用,我们是通过方法引用来使用已经存在的方案
  • 代码演示

public class Main {
    public static void main(String[] args) {
        Integer[] array = {2,4,5,6,1,3,7,10};

        //匿名内部类
        /*Arrays.sort(array, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });*/
        
        //lambda表达式
        Arrays.sort(array,(o1, o2) -> o2 - o1);

        //方法引用
        //静态方法要用类名去调用
        Arrays.sort(array,Main::subtraction);

        for (int i = 0; i < array.length; i++) {
            System.out.println(array[i]);
        }

    }
    public static int subtraction(int num1,int num2){
        return num2 - num1;
    }
}

方法引用符

  • 方法引用符

    • :: 该符号为引用运算符,而它所在的表达式被称为方法引用
  • 推导与省略

    • 如果使用Lambda,那么根据“可推导就是可省略”的原则,无需指定参数类型,也无需指定的重载形式,它们都将被自动推导
    • 如果使用方法引用,也是同样可以根据上下文进行推导
    • 方法引用是Lambda的孪生兄弟

引用类方法

引用类方法,其实就是引用类的静态方法

  • 格式

    类名::静态方法

  • 范例

Integer::parseInt

Integer类的方法:public static int parseInt(String s) 将此String转换为int类型数据
  • 练习描述

    • 定义一个接口(Converter),里面定义一个抽象方法 int convert(String s);
    • 定义一个测试类(ConverterDemo),在测试类中提供两个方法
      • 一个方法是:useConverter(Converter c)
      • 一个方法是主方法,在主方法中调用useConverter方法
interface Converter{
    public abstract int convert(String s);
}
public class ConverterDemo {
    public static void main(String[] args) {

        //lambda
        useConvert( s -> Integer.parseInt(s));//1234

        //方法引用
        useConvert(Integer::parseInt);//1234
    }
    public static void useConvert(Converter c){
        int num = c.convert("1234");
        System.out.println(num);
    }
}

  • 使用说明

    Lambda表达式被类方法替代的时候,它的形式参数全部传递给静态方法作为参数

引用对象的实例方法

引用对象的实例方法,其实就引用类中的成员方法

  • 格式
    对象::成员方法

  • 范例

"String"::toUpperCase

String类中的方法:public String toUpperCase() 
				将此String所有字符转换为大写
  • 练习描述

    • 定义一个类(PrintString),里面定义一个方法

    • public void printUpper(String s):把字符串参数变成大写的数据,然后在控制台输出

    • 定义一个接口(Printer),里面定义一个抽象方法

      void printUpperCase(String s)

    • 定义一个测试类(PrinterDemo),在测试类中提供两个方法

      • 一个方法是:usePrinter(Printer p)
      • 一个方法是主方法,在主方法中调用usePrinter方法
        代码演示
class PrintString{
    //把字符串参数变成大写的数据,然后在控制台输出
    public void printUpper(String s){
        String result = s.toUpperCase();
        System.out.println(result);
    }
}
interface Printer{
    void printUpperCase(String s);
}
public class MethodCitationDemo {
    public static void main(String[] args) {
        /*usePrinter(new Printer() {
            @Override
            public void printUpperCase(String s) {
                String result = s.toUpperCase();
                System.out.println(result);
            }
        });*/

        //方法引用
        usePrinter(new PrintString() :: printUpper);
    }
    public static void usePrinter(Printer p){
    	//传递实参给接口中的抽象方法
        p.printUpperCase("HelloWorld");
    }
}

使用说明

Lambda表达式被对象的实例方法替代的时候,它的形式参数全部传递给该方法作为参数

引用类的实例方法

​引用类的实例方法,其实就是引用类中的成员方法

  • 格式

    类名::成员方法

  • 范例

String::substring

public String substring(int beginIndex,int endIndex)

从beginIndex开始到endIndex结束,截取字符串。返回一个子串,子串的长度为endIndex-beginIndex

  • 练习描述

  • 定义一个接口(MyString),里面定义一个抽象方法:

String mySubString(String s,int x,int y);
  • 定义一个测试类(MyStringDemo),在测试类中提供两个方法

    • 一个方法是:useMyString(MyString my)
    • 一个方法是主方法,在主方法中调用useMyString方法
  • 代码演示

interface MyString{
    String mySubString(String s,int start,int end);
}
public class MyStringDemo {
    public static void main(String[] args) {
        useMyString((String s, int start, int end) ->
                s.substring(start, end));

        useMyString(String::substring);
    }
    public static void useMyString(MyString m){
    	//传递实参给接口中的抽象方法
        String s = m.mySubString("HelloWorld", 0, 5);
        System.out.println(s);
    }
}

引用构造器(构造方法)

引用构造器,其实就是引用构造方法
(就是为了创建对象)

  • 格式

    类名::new

  • 范例

    Student::new

  • 练习描述

    • 定义一个类(Student),里面有两个成员变量(name,age)
      并提供无参构造方法和带参构造方法,以及成员变量对应的get和set方法

    • 定义一个接口(StudentBuilder),里面定义一个抽象方法
      Student build(String name,int age);

    • 定义一个测试类(StudentDemo),在测试类中提供两个方法

      • 一个方法是:useStudentBuilder(StudentBuilder s)
      • 一个方法是主方法,在主方法中调用useStudentBuilder方法
  • 代码演示

public class StudentDemo {
    public static void main(String[] args) {
        useStudentBuilder(new StudentBuilder() {
            @Override
            public Student build(String name, int age) {
                return new Student(name,age);
            }
        });
        
        useStudentBuilder(Student::new);
    }
    public static void useStudentBuilder(StudentBuilder sb){
        Student s = sb.build("qixuan", 25);
        System.out.println(s.getName()+","+s.getAge());
    }
}
interface StudentBuilder{
    Student build(String name,int age);
}
class Student{
    private String name;
    private int 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;
    }

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

    public Student() {
    }
}

引用数组的构造方法

为了创建一个数组

  • 格式
    数组名::new
  • 范例
    int [ ] :: new
  • 代码演示
public class ArrayDemo {
    public static void main(String[] args) {
        //目的:创建一个指定类型的数组
        //需求:集合中存储一些整数,收集到数组当中

        ArrayList<Integer> list = new ArrayList<>();
        Collections.addAll(list,1,2,3,4,5);
        
        //收集到数组当中

        Integer[] arr1 = list.stream().toArray(new IntFunction<Integer[]>() {
            @Override
            public Integer[] apply(int value) {
                return new Integer[value];
            }
        });

        Integer[] arr2 = list.stream().toArray(Integer[]::new);
        
        System.out.println(Arrays.toString(arr1));//[1, 2, 3, 4, 5]
        System.out.println(Arrays.toString(arr2));//[1, 2, 3, 4, 5]
    }
}

方法引用综合练习

练习一:集合中存储一些字符串的数据,比如:fzx,20
收集到Student类型的数组中(使用方法引用)

public class Main {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();

        Collections.addAll(list,"fzx,20","qq,21","xx,25");

        //正常方法
        Student[] students1 = list.stream().map(new Function<String, Student>() {
            //可在Student类中写该方法来引用
            @Override
            public Student apply(String s) {
                String[] str = s.split(",");
                return new Student(str[0], Integer.parseInt(str[1]));
            }
        }).toArray(new IntFunction<Student[]>() {
            @Override
            public Student[] apply(int value) {
                return new Student[value];
            }
        });

        for (Student student : students1) {
            System.out.println(student);
        }

        //方法引用
        Student[] students2 = list.stream().map(Student::new).toArray(Student[]::new);

        System.out.println(Arrays.toString(students2));
    }
}
class Student{
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    //重写方法用于引用
    public Student(String s){
        this.name = s.split(",")[0];
        this.age = Integer.parseInt(s.split(",")[1]);
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Student() {
    }

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

练习二:创建集合添加学生对象,对象属性:name,age
只获取名字并放到数组当中(使用方法引用)

public class MainPractice {
    public static void main(String[] args) {
        ArrayList<Student> list = new ArrayList<>();

        Student s1 = new Student("fzx",20);
        Student s2 = new Student("zx",22);
        Student s3 = new Student("fx",23);
        Student s4 = new Student("fz",21);
        Collections.addAll(list, s1,s2,s3,s4);

        String[] str1 = list.stream().map(new Function<Student, String>() {
            @Override
            public String apply(Student student) {
                return student.getName();
            }
        }).toArray(String[]::new);

        System.out.println(Arrays.toString(str1));

        //方法引用
        String[] str2 = list.stream().map(Student::getName).toArray(String[]::new);

        System.out.println(Arrays.toString(str2));
    }
}
class Student{
    private String name;
    private int 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;
    }

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

    public Student() {
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值