JAVA基础知识|lambda与stream

lambda与stream是java8中比较重要两个新特性,lambda表达式采用一种简洁的语法定义代码块,允许我们将行为传递到函数中。之前我们想将行为传递到函数中,仅有的选择是使用匿名内部类,现在我们可以使用lambda表达式替代匿名内部类。在学习lambda表达式之前,建议各位看官先去学习一下匿名内部类(JAVA基础知识|内部类)。

stream提供了很多有用的api,方便了我们对集合的操作

一、lambda表达式

基本语法:
(parameters) -> expression

(parameters) ->{ statements; }

lambda表达式的重要特征:

  • 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
  • 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
  • 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
  • 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。

以下是一些简单的例子,便于我们理解这些特性:

        // 1. 不需要参数,返回值为5
        () -> 5

        // 2. 接收一个参数,()可以省略,返回其2倍的值
        x -> 2 * x

        // 3. 接受2个参数(数字),并返回他们的差值
        (x, y) ->x –y

        // 4. 接收2个int型整数,返回他们的和
        ( int x, int y) ->x + y

        // 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
        (String s) ->System.out.print(s)

二、lambda表达式使用

2.1、在for循环中使用

package com.my.controller;

import junit.framework.TestCase;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

/**
 * description:{description}
 * author:jyy
 * date:2018-01-09 16:43
 * modify:{modify}
 */
public class AppTest extends TestCase {

    @Test
    public void test() {

        List<String> list = new ArrayList<>();
        list.add("北京");
        list.add("上海");
        list.add("广州");
        list.add("深圳");

        for (String str : list) {
            System.out.println(str);
        }

        System.out.println("=================");

        list.forEach(str -> System.out.println(str));

    }

}

执行结果:

北京
上海
广州
深圳
=================
北京
上海
广州
深圳

2.2、替代匿名内部类使用

我们使用JAVA基础知识|内部类中的try catch示例

package com.my.controller;

import junit.framework.TestCase;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

/**
 * description:{description}
 * author:jyy
 * date:2018-01-09 16:43
 * modify:{modify}
 */
public class AppTest extends TestCase {

    @Test
    public void test() {

        //匿名内部类
        new ExceptionTemplate().execute(new CatchExceptionable() {
            @Override
            public void catchException() {
                System.out.println("代码");
            }
        });

        //lambda表达式
        new ExceptionTemplate().execute(() -> System.out.println("代码"));
    }

}

2.3、lambda表达式与Comparator类结合使用

package com.my.controller;

import junit.framework.TestCase;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

/**
 * description:{description}
 * author:jyy
 * date:2018-01-09 16:43
 * modify:{modify}
 */
public class AppTest extends TestCase {

    @Test
    public void test() {

        List<String> list = new ArrayList<>();
        list.add("BeiJing");
        list.add("ShangHai");
        list.add("GuangZhou");
        list.add("ShenZhen");

        list.sort(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.compareTo(o2);
            }
        });
        list.forEach(str -> System.out.println(str));

        System.out.println("==============");

        List<String> list2 = new ArrayList<>();
        list2.add("BeiJing");
        list2.add("ShangHai");
        list2.add("GuangZhou");
        list2.add("ShenZhen");

        //list2.sort((String o1,String o2) -> o1.compareTo(o2));
        Comparator<String> comparator =(String o1,String o2) -> o1.compareTo(o2);
        list2.sort(comparator);
        list2.forEach(str -> System.out.println(str));

    }
}

执行结果:

BeiJing
GuangZhou
ShangHai
ShenZhen
==============
BeiJing
GuangZhou
ShangHai
ShenZhen

三、流stream

Java 8 中的stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作(aggregate operation),或者大批量数据操作 (bulk data operation)。stream API 借助于同样新出现的 lambda 表达式,极大的提高编程效率和程序可读性。同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势

生成流的两种方式:

  • stream() ? 为集合创建串行流。
  • parallelStream() ? 为集合创建并行流。

下面我们就来使用stream提供的各种API:

3.1、筛选和切片

方法 描述
filter 从流中过滤元素
distinct 通过流所生成的元素的hashCode()和equals()方法去重
limit 截断流,选取前n个元素
skip 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足n个,则返回一个空流

package com.my.po;

/**
 * description:{description}
 * author:jyy
 * date:2018-02-11 11:06
 * modify:{modify}
 */
public class Employee {
    private String id;
    private String name;
    private double salary;
    private String sex;

    public Employee(String id, String name, double salary,String sex) {
        this.id = id;
        this.name = name;
        this.salary = salary;
        this.sex=sex;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "id=‘" + id + ‘\‘‘ +
                ", name=‘" + name + ‘\‘‘ +
                ", salary=" + salary +
                ", sex=‘" + sex + ‘\‘‘ +
                ‘}‘;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Employee employee = (Employee) o;

        return id.equals(employee.id);
    }

    @Override
    public int hashCode() {
        return id.hashCode();
    }
}

package com.my.controller;

import com.my.po.Employee;
import junit.framework.TestCase;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * description:{description}
 * author:jyy
 * date:2018-01-09 16:43
 * modify:{modify}
 */
public class AppTest extends TestCase {

    @Test
    public void test() {
        Employee[] employees = {
                new Employee("1001", "李明", 5000, "male"),
                new Employee("1002", "王明", 7000, "male"),
                new Employee("1003", "张丽", 10000, "female"),
                new Employee("1004", "谢楠", 11000, "female"),
                new Employee("1004", "谢楠", 11000, "female")
        };
        List<Employee> list = Arrays.asList(employees);

        //forEach,查询所有数据
        list.stream().forEach(e -> System.out.println(e.toString()));

        //filter,查询集合中所有的女性
        list.stream().filter(e -> Objects.equals(e.getSex(), "female")).forEach(e -> System.out.println(e.toString()));
        //查询集合中薪资大于6000的雇员
        list.stream().filter(e -> e.getSalary() > 7000).forEach(e -> System.out.println(e));

        //limit,查询前两条数据
        list.stream().limit(2).forEach(e -> System.out.println(e.toString()));

        //distinct,去重,利用Employee对象中的hashCode()和equals()方法
        list.stream().distinct().forEach(e -> System.out.println(e));

        //skip,跳过前两个
        list.stream().skip(2).forEach(e -> System.out.println(e));

    }
}

3.2、映射

方法 描述
 map(Function f)  接受一个函数作为参数,并将函数应用到每一个元素上,返回新的元素
 mapToDouble(ToDoubleFunction f)  返回的新元素为double类型
 mapToInt(ToIntFunction f)  返回的新元素为int类型
 mapToLong(ToLongFunction f)  返回的新元素为long类型
 flatMap(Function f)  操作多层嵌套的流,使其扁平化

3.2.1、map

        Employee[] employees = {
                new Employee("1001", "李明", 5000, "male"),
                new Employee("1002", "王明", 7000, "male"),
                new Employee("1003", "张丽", 10000, "female"),
                new Employee("1004", "谢楠", 11000, "female"),
                new Employee("1004", "谢楠", 11000, "female")
        };
        List<Employee> list = Arrays.asList(employees);

        //map
        list.stream().map(e -> e.getSalary()).forEach(e -> System.out.println(e));

执行结果:

5000.0
7000.0
10000.0
11000.0
11000.0

可以看出,集合list经过map操作之后,类型已经改变。具体什么类型,由返回值决定

3.2.2、mapToDouble、mapToInt、mapToLong

        Employee[] employees = {
                new Employee("1001", "李明", 5000, "male"),
                new Employee("1002", "王明", 7000, "male"),
                new Employee("1003", "张丽", 10000, "female"),
                new Employee("1004", "谢楠", 11000, "female"),
                new Employee("1004", "谢楠", 11000, "female")
        };
        List<Employee> list = Arrays.asList(employees);

        list.stream().mapToDouble(e -> e.getSalary()).forEach(e -> System.out.println(e));

执行结果:

5000.0
7000.0
10000.0
11000.0
11000.0

3.2.3、flatMap

        Employee[] employees1 = {
                new Employee("1001", "李明", 5000, "male"),
                new Employee("1002", "王明", 7000, "male"),
                new Employee("1003", "张丽", 10000, "female"),
                new Employee("1004", "谢楠", 11000, "female")
        };
        Employee[] employees2 = {
                new Employee("1005", "Marry", 5000, "male"),
                new Employee("1006", "Linda", 7000, "male"),
                new Employee("1007", "Cris", 10000, "female")
        };
        List<Employee[]> list = new ArrayList<>();
        list.add(employees1);
        list.add(employees2);
        list.stream().flatMap(e -> Arrays.stream(e)).forEach(e -> System.out.println(e.toString()));

执行结果:

Employee{id=‘1001‘, name=‘李明‘, salary=5000.0, sex=‘male‘}
Employee{id=‘1002‘, name=‘王明‘, salary=7000.0, sex=‘male‘}
Employee{id=‘1003‘, name=‘张丽‘, salary=10000.0, sex=‘female‘}
Employee{id=‘1004‘, name=‘谢楠‘, salary=11000.0, sex=‘female‘}
Employee{id=‘1005‘, name=‘Marry‘, salary=5000.0, sex=‘male‘}
Employee{id=‘1006‘, name=‘Linda‘, salary=7000.0, sex=‘male‘}
Employee{id=‘1007‘, name=‘Cris‘, salary=10000.0, sex=‘female‘}

原文地址:https://www.cnblogs.com/maikucha/p/8435906.html

时间: 2024-10-31 10:07:44

JAVA基础知识|lambda与stream的相关文章

沉淀,再出发:Java基础知识汇总

沉淀,再出发:Java基础知识汇总 一.前言 不管走得多远,基础知识是最重要的,这些知识就是建造一座座高楼大厦的基石和钢筋水泥.对于Java这门包含了编程方方面面的语言,有着太多的基础知识了,从最初的语法,对象的定义,类.接口.继承.静态.动态.重载.覆盖这些基本的概念和使用方法,到稍微高级一点的多线程,文件读写,网络编程,GUI使用,再到之后的反射机制.序列化.与数据库的结合等高级一点的用法,最后将设计模式应用其中,产生了一个个新的概念,比如Spring.Spring MVC.Hibernat

JAVA基础知识|Socket

一.什么是Socket? Socket本身并不是协议,是一套完成TCP.UDP协议的调用接口(API),通过socket我们才能使用TCP/IP协议(JAVA基础知识|TCP/IP协议).Socket的出现只是使得程序员更方便地使用TCP/IP协议栈而已,是对TCP/IP协议的抽象,从而形成了我们知道的一些最基本的函数接口. Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket ,另一个运行于服务器端,称为ServerSocket . HTTP请求是基于Sock

毕向东—Java基础知识总结(超级经典)

Java基础知识总结(超级经典) 写代码: 1,明确需求.我要做什么? 2,分析思路.我要怎么做?1,2,3. 3,确定步骤.每一个思路部分用到哪些语句,方法,和对象. 4,代码实现.用具体的java语言代码把思路体现出来. 学习新技术的四点: 1,该技术是什么? 2,该技术有什么特点(使用注意): 3,该技术怎么使用.demo 4,该技术什么时候用?test. ------------------------------------------------------ 一:java概述: 19

Java基础知识总结(超级经典)

Java基础知识总结(超级经典) 写代码: 1,明确需求.我要做什么? 2,分析思路.我要怎么做?1,2,3. 3,确定步骤.每一个思路部分用到哪些语句,方法,和对象. 4,代码实现.用具体的java语言代码把思路体现出来. 学习新技术的四点: 1,该技术是什么? 2,该技术有什么特点(使用注意): 3,该技术怎么使用.demo 4,该技术什么时候用?test. —————————————————————————————————————————————————————— 一:java概述: 19

java基础知识回顾之java Thread类学习(八)--java多线程通信等待唤醒机制经典应用(生产者消费者)

 *java多线程--等待唤醒机制:经典的体现"生产者和消费者模型 *对于此模型,应该明确以下几点: *1.生产者仅仅在仓库未满的时候生产,仓库满了则停止生产. *2.消费者仅仅在有产品的时候才能消费,仓空则等待. *3.当消费者发现仓储没有产品可消费的时候,会唤醒等待生产者生产. *4.生产者在生产出可以消费的产品的时候,应该通知等待的消费者去消费. 下面先介绍个简单的生产者消费者例子:本例只适用于两个线程,一个线程生产,一个线程负责消费. 生产一个资源,就得消费一个资源. 代码如下: pub

java基础知识回顾之java Thread类学习(七)--java多线程通信等待唤醒机制(wait和notify,notifyAll)

1.wait和notify,notifyAll: wait和notify,notifyAll是Object类方法,因为等待和唤醒必须是同一个锁,不可以对不同锁中的线程进行唤醒,而锁可以是任意对象,所以可以被任意对象调用的方法,定义在Object基类中. wait()方法:对此对象调用wait方法导致本线程放弃对象锁,让线程处于冻结状态,进入等待线程的线程池当中.wait是指已经进入同步锁的线程,让自己暂时让出同步锁,以便使其他正在等待此锁的线程可以进入同步锁并运行,只有其它线程调用notify方

java基础知识回顾之java Thread类学习(六)--java多线程同步函数用的锁

1.验证同步函数使用的锁----普通方法使用的锁 思路:创建两个线程,同时操作同一个资源,还是用卖票的例子来验证.创建好两个线程t1,t2,t1线程走同步代码块操作tickets,t2,线程走同步函数封装的代码操作tickets,同步代码块中的锁我们可以指定.假设我们事先不知道同步函数用的是什么锁:如果在同步代码块中指定的某个锁(测试)和同步函数用的锁相同,就不会出现线程安全问题,如果锁不相同,就会发生线程安全问题. 看下面的代码:t1线程用的同步锁是obj,t2线程在操作同步函数的资源,假设不

第1天:了解Java基础知识

Java的优势 1. 简单 不像C或者C++语言,Java中省去了对指针的操作.但是,Java中并没有省去指针,代替指针的是一种新的变量--引用,引用也是保存一个对象的内存地址. 2.方便 Java虚拟机自带垃圾回收器,能够自动回收内存资源.而C和C++语言,需要开发人员手动进行内存资源回收. 3.安全 不支持指针操作 4.平台无关性 Java语言是跨平台的,一次编译,到处运行. 而且,不同平台,C语言中数据类型所占的位数是不同的,而Java语言中,数据类型所占的位数是固定的. 5.面向对象 J

JAVA基础知识-java文化基础和运行环境

JAVA基础知识 1,java是95年sun公司推出的开发语言,发展很快,09年被oracle公司收购.至今分为SE.ME.EE三个发展方向和软件版本. 2,运行java的环境主要是通过JVM(java virtual machine)实现的.首先编写.java结尾的源文件,通过编译器编译成.class结尾的字节码文件,然后通过解释器实现在不同平台上一致运行的效果. 3,jvm,jre和jdk的区别:jvm,java虚拟机:jre,java运行环境,jdk:java开发工具包. 4,jdk的下载