java语法糖

前沿:在美团已经实习了一段时间,在看业务代码的时候,有一些我不熟悉的语法操作,百度了一下,这些简便的写法其实是语法糖。

  • 语法糖:语法糖就是一种便捷写法
  • 注:下面的只是我自己想当然认为它们是语法糖

1、::双冒号操作符

1.1 使用方式

:: 是是JDK8的一种语法糖,根据不同的使用情景,其使用方式为以下的四种情景:

  • 实例对象::实例方法
  • 该方式的一个典型用法就是 x -> System.out.println(x) 可以替换成 System.out::println
  • System类中有一个静态成员对象out,其是printStream类的实例(即在System类中为public static final printStream out ,且out是static的),因此,System.out是printStream的实例化对象,System.out 表示屏幕输出,这时候还只是字节流而已,当调用printStream的方法println()是就表示用什么用的方式打印输出的关系了。
  • 原本应该写为:.forEach(element -> {System.out.println(element)})但是System.out.println的参数和传递的参数element 的类型完全匹配,所以这样的时候就可以简化为:.forEach(System.out::println)
  • 类名::实例方法
  • 类名::静态方法
  • 类名::new

当创建对象 () -> new ArrayList<>()时,可以替换为 ArrayList::new,因为 new关键字实际上调用的是ArrayList的构造方法

在这里插入图片描述

Class 是类名,产生于class Class { }。object 是实例对象,产生于 Class object = new Class()

在使用的过程中要注意以下几点,

  • 方法后面并没有()
  • 懒加载方法是否调用要看调用方使用情况

1.2 举例

package org.example;

import java.util.Arrays;
import java.util.List;
import java.util.function.*;

public class Sugar {
    private int paoPaoTang = 0;
    private int aErBeiSi = 1;

    /**
     * 下面的两个方法分别是:无返回值的实例方法、有返回值的实例方法
     * @param a
     * @param s
     */
    public void noValueInstance(int a, String s){
        int b = Integer.valueOf(s).intValue();
        int sum = a +b + paoPaoTang +aErBeiSi;
        System.out.println(String.format("我没有返回值,我输出的值是:%d", sum));
    }
    public int hasValueInstance(int a, String s){
        int b = Integer.valueOf(s).intValue();
        int sum = a + b +paoPaoTang + aErBeiSi;
        System.out.println("我有返回值");
        return sum;
    }

    /**
     * 下面的两个方法分别是:无返回值的静态方法、有返回值的静态方法
     * @param choice
     */
    public static void noValueStatic(int choice){
        if(choice==0){
            System.out.println("我是泡泡糖");
        }else{
            System.out.println("我是阿尔卑斯");
        }
    }
    public static int hasValueStatic(int choice){
        Sugar sugar = new Sugar();
        if(choice==0){
            return sugar.paoPaoTang;
        }else{
            return sugar.aErBeiSi;
        }
    }

    public static void printValur(String str) {
        System.out.println("print value : " + str);
    }

    public static void main(String[] args) {

        List<String> al = Arrays.asList("a", "b", "c", "d");
        al.forEach(Sugar::printValur);
        // 下面的方法和上面等价的
        Consumer<String> methodParam = Sugar::printValur;
        al.forEach(x -> methodParam.accept(x));
        System.out.println("*************************************************");

        int a = 1;
        String s = "2";
        Sugar sugar = new Sugar();

        /**
         *  无返回值的实例方法
         *  请注意:BiConsumer无返回值,它接受两个参数作为参数。
         */
        BiConsumer<Integer, String> noValueInstance = sugar::noValueInstance;
        noValueInstance.accept(a, s);

        /**
         * 有返回值的实例方法。
         * 请注意:BiFunction接受两个参数并返回一个值。在声明BiFunction时,我们需要告诉我们将传递什么类型的参数以及什么是返回类型。
         */
        // 方式一
        ToIntBiFunction<Integer, String> hasValueInstance = sugar::hasValueInstance;
        int result = hasValueInstance.applyAsInt(a, s);
        System.out.println(result);
        // 方式二
        BiFunction<Integer, String, Integer> hasValueInstance1 = sugar::hasValueInstance;
        int result1 =  hasValueInstance1.apply(a, s);
        System.out.println(result1);

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

        /**
         * 无返回值的静态方法
         *
         * Consumer的作用就是定义一个函数,然后对其进行消费处理,(accept方法),其接受一个参数,但无返回值
         */
        Consumer<Integer> noValueStatic = Sugar::noValueStatic;
        noValueStatic.accept(0);

        IntConsumer noValueStatic1 = Sugar::noValueStatic;
        noValueStatic1.accept(1);

        /**
         * 有返回值的静态方法
         * 
         * Function的作用就是定义一个函数,其功能方法是apply,其接受一个参数,有返回值
         */
        Function<Integer, Integer> hasValueStatic = Sugar::hasValueStatic;
        int res = hasValueStatic.apply(0);
        System.out.println(res);

        IntFunction<Integer> hasValueStatic1 = Sugar::hasValueStatic;
        int res1 = hasValueStatic.apply(1);
        System.out.println(res1);


    }
}

Consumer与Function参考本篇文章
参考:https://blog.csdn.net/qq_27389705/article/details/89083963
参考:https://www.cnblogs.com/yanlong300/p/9209243.html


2、->

2.1 Java 8 函数式接口

2.1.1 函数式接口

函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口,函数式接口可以被隐式转换为 lambda 表达式。如定义了一个函数式接口如下:

@FunctionalInterface
interface GreetingService 
{
    void sayMessage(String message);
}

那么就可以使用Lambda表达式来表示该接口的一个实现 (注:JAVA 8 之前一般是用匿名类实现的):

GreetingService greetService1 = message -> System.out.println("Hello " + message);

函数式接口可以对现有的函数友好地支持 lambda

2.1.2 函数式接口实例

Predicate <T> 接口是一个函数式接口,它接受一个输入参数 T,返回一个布尔值结果。该接口包含多种默认方法来将Predicate组合成其他复杂的逻辑(比如:与,或,非),该接口用于测试对象是 true 或 false。我们可以通过以下实例(Java8Tester.java)来了解函数式接口 Predicate 的使用:

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
 
public class Java8Tester {
   public static void main(String args[]){
      List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
        
      // Predicate<Integer> predicate = n -> true
      // n 是一个参数传递到 Predicate 接口的 test 方法
      // n 如果存在则 test 方法返回 true
        
      System.out.println("输出所有数据:");
        
      // 传递参数 n
      eval(list, n->true);
        
      // Predicate<Integer> predicate1 = n -> n%2 == 0
      // n 是一个参数传递到 Predicate 接口的 test 方法
      // 如果 n%2 为 0 test 方法返回 true
        
      System.out.println("输出所有偶数:");
      eval(list, n-> n%2 == 0 );
        
      // Predicate<Integer> predicate2 = n -> n > 3
      // n 是一个参数传递到 Predicate 接口的 test 方法
      // 如果 n 大于 3 test 方法返回 true
        
      System.out.println("输出大于 3 的所有数字:");
      eval(list, n-> n > 3 );
   }
    
   public static void eval(List<Integer> list, Predicate<Integer> predicate) {
      for(Integer n: list) {
        
         if(predicate.test(n)) {
            System.out.println(n + " ");
         }
      }
   }
}

执行以上结果:

$ javac Java8Tester.java 
$ java Java8Tester
输出所有数据:
1 
2 
3 
4 
5 
6 
7 
8 
9 
输出所有偶数:
2 
4 
6 
8 
输出大于 3 的所有数字:
4 
5 
6 
7 
8 
9 
interface Person{
    void say(String t);
}

class AnimalSay{  
     public static void saySomething(String something,Person person) {
         person.say(something);
     }
}

public class Mian {
     public static void main(String[] args) {  
         Person xiaoMing = (x) -> { System.out.println(x); };    
        //xiaoMing.say("hello");	//1
         AnimalSay.saySomething("hello", xiaoMing );           //2
		// 可以直接把 lambda 表达式直接放在需要的位置。这时候 lambda 就可以自动变成所需类
         //AnimalSay.saySomething("hello", (x)->{System.out.println(x)};);    //3
     }
}
2.1.3 链接

参考链接


2.2 Java Lambda 表达式

2.2.1 特性
  • Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。
  • Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中),使用 Lambda 表达式可以使代码变的更加简洁紧凑。
  • Labmda表达式一般用来实现一个函数式接口,省去了之前需要专为他编写一个实现类或者匿名内部类的代码,直接对接口进行实现。因为该接口中只有一个抽象方法,因此不会有冲突的可能。
2.2.2 语法

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)
2.2.3 举例
public class Java8Tester {
   public static void main(String args[]){
      Java8Tester tester = new Java8Tester();
        
      // 类型声明
      MathOperation addition = (int a, int b) -> a + b;
        
      // 不用类型声明
      MathOperation subtraction = (a, b) -> a - b;
        
      // 大括号中的返回语句
      MathOperation multiplication = (int a, int b) -> { return a * b; };
        
      // 没有大括号及返回语句
      MathOperation division = (int a, int b) -> a / b;
        
      System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
      System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));
      System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication));
      System.out.println("10 / 5 = " + tester.operate(10, 5, division));
        
      // 不用括号
      GreetingService greetService1 = message ->
      System.out.println("Hello " + message);
        
      // 用括号
      GreetingService greetService2 = (message) ->
      System.out.println("Hello " + message);
        
      greetService1.sayMessage("Runoob");
      greetService2.sayMessage("Google");
   }
    
   interface MathOperation {
      int operation(int a, int b);
   }
   private int operate(int a, int b, MathOperation mathOperation){
      return mathOperation.operation(a, b);
   }
    
   interface GreetingService {
      void sayMessage(String message);
   }
}
执行以上脚本,输出结果为:
```java
$ javac Java8Tester.java 
$ java Java8Tester
10 + 5 = 15
10 - 5 = 5
10 x 5 = 50
10 / 5 = 2
Hello Runoob
Hello Google

使用 Lambda 表达式需要注意以下两点:

  • Lambda 表达式用于只有一个匿名方法的函数式接口主要用来定义行内执行的方法类型接口,例如,一个简单方法接口。在上面例子中,我们使用各种类型的Lambda表达式来定义MathOperation接口的方法。然后我们定义了sayMessage的执行。
  • Lambda 表达式免去了使用匿名方法的麻烦,并且给予Java简单但是强大的函数化的编程能力。

在这里插一个多线程的lambda表达式使用技巧:

链接:https://www.zhihu.com/question/302776698/answer/1522159326


public class SynchronizedTest {
    public synchronized void method1() {
        System.out.println("Method 1 start");
        try {
            System.out.println("Method 1 execute");
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Method 1 end");
    }

    public synchronized void method2() {
        System.out.println("Method 2 start");
        try {
            System.out.println("Method 2 execute");
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Method 2 end");
    }

    public static void main(String[] args) {
        // 一种最简洁的启动方法
        //new Thread( ()-> new SynchronizedTest().method1() ).start();
        
        //新建实例对象的启动方法
        final SynchronizedTest test = new SynchronizedTest();
        new Thread(test::method1).start();
        new Thread( ()-> test.method1() ).start();
        //显式的赋值Runnable后再启动
        Runnable tt = test::method1;
        new Thread(tt).start();
        new Thread(test::method2).start();
    }
}

//运行完后对结果有没有疑问? 为什么2后面还有1?
Method 1 start
Method 1 execute
Method 1 end
Method 2 start
Method 2 execute
Method 2 end
Method 1 start
Method 1 execute
Method 1 end
Method 1 start
Method 1 execute
Method 1 end
2.2.4 变量作用域

lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。

2.2.5 链接

参考链接

2.3 与foreach()搭配更美味

Java8 推出的lambda表达式,与一众的 => 不同,Java选择了 -> 做为箭头符号,lambda表达式的基本格式是这样的:

( )->{ }

具体是什么意思呢,这里就要提一下使用lambda表达式的前提了,labmda表达式一般用来实现一个函数式接口,比如java.lang.Iterable 的 foreach(xxx)方法中的xxx位置需要一个 Consumer 接口类,

default void forEach(Consumer<? super T> action) {
    Objects.requireNonNull(action);
    for (T t : this) {
        action.accept(t);
    }
}

而 Consumer 正好是一个函数式接口(@FunctionalInterface 注解了解一下)。

@FunctionalInterface
public interface Consumer<T> {
    ...
    void accept(T t);
    ...
}

这时候可以这么用lamda表达式来实现一个函数式接口,即 Consumer one = (x) -> { System.out.println(x) } ,然后再把 one 传进去forEach就可以,与上面的代码结合起来看,x就是accept中的t,花括号里没有return是因为accept返回值是void因为 Consumer 接口中只有一个方法,因此不会有冲突的可能)。

//第一种
Consumer one = (x) -> { System.out.println(x);};
Iterable.foreach(one);
//第二种
Iterable.foreach( x->System.out.println(x) );

3 Foreach

3.1 特性

  • foreach语句是for语句的特殊简化版本,提高了代码的可读性和安全性(不用怕数组越界),但是foreach语句并不能完全取代for语句(在用到对集合或者数组索引的情况下,foreach显得力不从心,这个时候是用for语句的时候了),然而,任何的foreach语句都可以改写为for语句版本。
  • foreach一般结合泛型使用
  • foreach并不是一个关键字,习惯上将这种特殊的for语句格式称之为“foreach”语句

3.2 语句格式:

for(元素类型t 元素变量x : 遍历对象obj){
     引用了x的java语句;
}

3.3

  • 特别地,一个经常见到的例子是:原本应该写为:.forEach(element -> {System.out.println(element)}),但是System.out.println的参数和传递的参数element 的类型完全匹配,所以这样的时候就可以简化为:.forEach(System.out::println)

  • list.forEach((t) -> System.out.println(t)),如果还不明白的话,也可以这样,list.forEach((String t) -> System.out.println(t));

3.4 举例

3.4.1
package org.example;

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

public class Foreach {
	// https://www.zhihu.com/question/302776698/answer/1522159326
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");

        list.forEach(System.out::println);
        list.forEach((t)->System.out.println(t));
        list.forEach((String t)->System.out.println(t));
    }
}


a
b
c
a
b
c
a
b
c
3.4.2
public class TestArray {   
	 /**  
      * 集合转换为一维数组  
      */  
     public void listToArray() {   
         //创建List并添加元素   
          List<String> list = new ArrayList<String>();   
          list.add("1");   
          list.add("3");   
          list.add("4");   
   
         //利用froeach语句输出集合元素   
         System.out.println("----2----froeach语句输出集合元素");   
         for (String x : list) {   
              System.out.println(x);   
         }   
         //将ArrayList转换为数组   
         Object s[] = list.toArray();   
   
         //利用foreach语句输出集合元素   
         System.out.println("----2----froeach语句输出集合转换而来的数组元素");   
         for (Object x : s) {   
              System.out.println(x.toString()); //逐个输出数组元素的值   
         }   
    }   
	public static void main(String args[]) {   
     	TestArray test = new TestArray();            
  		test.listToArray();   
  	}   
}  

参考:https://www.cnblogs.com/elleniou/archive/2012/04/27/2473050.html


4、list.stream().map().collect(Collectors.toList())

4.1.0 问题来源

userList:User实体类对象集合
User:实体类
getId:实体类属性的方法

  • List ids= userList.stream().map(User::getId).collect(Collectors.toList())
  • 或者 把数据放到map根据user.getId(条件) ,再转换成list
  • List ids= userList.stream().map(user->user.getId()).collect(Collectors.toList());

4.1 函数说明

4.1.1 stream()
  • stream()把一个源数据(可以是集合,数组,I/O channel, 产生器generator 等)转化成流
  • Java8提供了Stream(流)处理集合,它可以对集合进行操作,可以执行非常复杂的查找、过滤和映射数据等操作
  • Stream API 借助于同样新出现的Lambda表达式,极大的提高编程效率和程序可读性

创建UserService.class(用户信息业务逻辑类):

import com.pjb.streamdemo.entity.User;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
 
/**
 * 用户信息业务逻辑类
 * @author pan_junbiao
 **/
public class UserService
{
    /**
     * 获取用户列表
     */
    public static List<User> getUserList()
    {
        List<User> userList = new ArrayList<User>();
        userList.add(new User(1, "pan_junbiao的博客_01", "男", 32, "研发部", BigDecimal.valueOf(1600)));
        userList.add(new User(2, "pan_junbiao的博客_02", "男", 30, "财务部", BigDecimal.valueOf(1800)));
        userList.add(new User(3, "pan_junbiao的博客_03", "女", 20, "人事部", BigDecimal.valueOf(1700)));
        userList.add(new User(4, "pan_junbiao的博客_04", "男", 38, "研发部", BigDecimal.valueOf(1500)));
        userList.add(new User(5, "pan_junbiao的博客_05", "女", 25, "财务部", BigDecimal.valueOf(1200)));
        return userList;
    }
}

4.1.2 forEach()
  • forEach()迭代流中的每个数据
  • 例子1:
/**
 * 使用forEach()遍历列表信息
 * @author pan_junbiao
 */
@Test
public void forEachTest()
{
    //获取用户列表
    List<User> userList = UserService.getUserList();
 
    //遍历用户列表
    userList.forEach(System.out::println);
}

上述遍历语句等同于以下语句:
userList.forEach(user -> {System.out.println(user);});

在这里插入图片描述

  • 例子2,以下代码片段使用 forEach() 输出了10个随机数。
Random random = new Random();
random.ints().limit(10).forEach(System.out::println);

4.1.3 filter(T -> boolean)
  • filter()方法通过设置的条件过滤列表数据
  • 例子1,获取部门为“研发部”的用户列表。
/**
 * 使用filter()过滤列表信息
 * @author pan_junbiao
 */
@Test
public void filterTest()
{
    //获取用户列表
    List<User> userList = UserService.getUserList();
 
    //获取部门为“研发部”的用户列表
    userList = userList.stream().filter(user -> user.getDepartment() == "研发部").collect(Collectors.toList());
 
    //遍历用户列表
    userList.forEach(System.out::println);
}

在这里插入图片描述

  • 例子2,以下代码片段使用 filter 方法过滤出空字符串:
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
// 获取空字符串的数量
int count = strings.stream().filter(string -> string.isEmpty()).count();


// parallelStream 是流并行处理方法,我们可以很容易的在顺序运行和并行直接切换。使用 parallelStream 来输出空字符串的数量:
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
// 获取空字符串的数量
int count = strings.parallelStream().filter(string -> string.isEmpty()).count();


4.1.4 findAny() 和 findFirst()
  • 使用 findAny() 和 findFirst() 获取第一条数据。
  • 例子1,获取用户名称为“pan_junbiao的博客_02”的用户信息,如果未找到则返回null。
/**
 * 使用findAny()获取第一条数据
 * @author pan_junbiao
 */
@Test
public void findAnytTest()
{
    //获取用户列表
    List<User> userList = UserService.getUserList();
 
    //获取用户名称为“pan_junbiao的博客_02”的用户信息,如果没有找到则返回null
    User user = userList.stream().filter(u -> u.getName().equals("pan_junbiao的博客_02")).findAny().orElse(null);
 
    //打印用户信息
    System.out.println(user);
}

在这里插入图片描述

注意:findFirst() 和 findAny() 都是获取列表中的第一条数据,但是findAny()操作,返回的元素是不确定的,对于同一个列表多次调用findAny()有可能会返回不同的值。使用findAny()是为了更高效的性能。如果是数据较少,串行地情况下,一般会返回第一个结果,如果是并行(parallelStream并行流)的情况,那就不能确保是第一个。
例如:使用parallelStream并行流(parallelStream方法能生成并行流),findAny() 返回的就不一定是第一条数据。
User user = userList.parallelStream().filter(u -> u.getName().startsWith("p")).findAny().orElse(null);


4.1.5 map(T -> R) 和 flatMap(T -> Stream)
  • 使用 map() 将流中的每一个元素 T 映射为 R(映射每个元素得到对应的结果
  • 使用 flatMap() 将流中的每一个元素 T 映射为一个流,再把每一个流连接成为一个流。
  • 例子1,使用 map() 方法获取用户列表中的名称列。
/**
 * 使用map()获取列元素
 * @author pan_junbiao
 */
@Test
public void mapTest()
{
    //获取用户列表
    List<User> userList = UserService.getUserList();
 
    //获取用户名称列表
    List<String> nameList = userList.stream().map(User::getName).collect(Collectors.toList());
    //或者:List<String> nameList = userList.stream().map(user -> user.getName()).collect(Collectors.toList());
 
    //遍历名称列表
    nameList.forEach(System.out::println);
}

不想要返回List列表想要的返回的结果为数组类型,写法如下:

//数组类型
String[] nameArray = userList.stream().map(User::getName).collect(Collectors.toList()).toArray(new String[userList.size()]);

在这里插入图片描述

  • 例子2,以下代码片段使用 map 输出了元素对应的平方数:
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
// 获取对应的平方数
List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());
  • 例子3,使用 flatMap() 将流中的每一个元素连接成为一个流。
/**
 * 使用flatMap()将流中的每一个元素连接成为一个流
 * @author pan_junbiao
 */
@Test
public void flatMapTest()
{
    //创建城市
    List<String> cityList = new ArrayList<String>();
    cityList.add("北京;上海;深圳;");
    cityList.add("广州;武汉;杭州;");
 
    //分隔城市列表,使用 flatMap() 将流中的每一个元素连接成为一个流。
    cityList = cityList.stream()
            .map(city -> city.split(";"))
            .flatMap(Arrays::stream)
            .collect(Collectors.toList());
 
    //遍历城市列表
    cityList.forEach(System.out::println);
}

在这里插入图片描述


4.1.6 distinct()
  • 使用 distinct() 方法可以去除重复的数据。
  • 例子1,获取部门列表,并去除重复数据。
/**
 * 使用distinct()去除重复数据
 * @author pan_junbiao
 */
@Test
public void distinctTest()
{
    //获取用户列表
    List<User> userList = UserService.getUserList();
 
    //获取部门列表,并去除重复数据
    List<String> departmentList = userList.stream().map(User::getDepartment).distinct().collect(Collectors.toList());
 
    //遍历部门列表
    departmentList.forEach(System.out::println);
}

在这里插入图片描述


4.1.7 limit(long n) 和 skip(long n)
  • limit(long n) 方法用于返回前n条数据,skip(long n) 方法用于跳过前n条数据
  • 例子1,获取用户列表,要求跳过第1条数据后的前3条数据。
/**
 * limit(long n)方法用于返回前n条数据
 * skip(long n)方法用于跳过前n条数据
 * @author pan_junbiao
 */
@Test
public void limitAndSkipTest()
{
    //获取用户列表
    List<User> userList = UserService.getUserList();
 
    //获取用户列表,要求跳过第1条数据后的前3条数据
    userList = userList.stream()
            .skip(1)
            .limit(3)
            .collect(Collectors.toList());
 
    //遍历用户列表
    userList.forEach(System.out::println);
}

在这里插入图片描述

  • 例子2, 以下代码片段使用 limit 方法打印出 10 条数据:
Random random = new Random();
random.ints().limit(10).forEach(System.out::println);
4.1.8 sorted() / sorted((T, T) -> int)
  • 如果流中的元素的类实现了 Comparable 接口,即有自己的排序规则,那么可以直接调用 sorted() 方法对元素进行排序,如 Stream。反之, 需要调用 sorted((T, T) -> int) 实现 Comparator 接口。
  • 例子1,根据用户年龄进行排序。
/**
 * 使用 sorted() 排序
 * @author pan_junbiao
 */
@Test
public void sortedTest()
{
    //获取用户列表
    List<User> userList = UserService.getUserList();
 
    //根据年龄排序(升序)
    userList = userList.stream().sorted((u1, u2) -> u1.getAge() - u2.getAge()).collect(Collectors.toList());
    //推荐:userList = userList.stream().sorted(Comparator.comparingInt(User::getAge)).collect(Collectors.toList());
    //降序:userList = userList.stream().sorted(Comparator.comparingInt(User::getAge).reversed()).collect(Collectors.toList());
 
    //遍历用户列表
    userList.forEach(System.out::println);
}

在这里插入图片描述

  • 例子2,以下代码片段使用 sorted 方法对输出的 10 个随机数进行排序:
Random random = new Random();
random.ints().limit(10).sorted().forEach(System.out::println);
4.1.9 Collectors()
  • Collectors()类实现了很多归约操作,例如将流转换成集合和聚合元素。Collectors 可用于返回列表或字符串:
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
System.out.println("筛选列表: " + filtered);

String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
System.out.println("合并字符串: " + mergedString);

4.2 参考链接

5、Enum类

https://blog.csdn.net/javazejian/article/details/71333103
https://blog.csdn.net/qq_27093465/article/details/52180865

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

还能坚持

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值