java8 stream理解及示例

一、lambda表达式

语法:

(parameters) -> expression
或
(parameters) ->{ statements; }

parameters是参数,expression是表达式,statements是代码块。

lambda表达式,其实就是匿名函数。

->左侧是方法参数,参数可以有多个。->右侧是方法内容,也可以直接是方法的返回值。

比如 x->x+5,表示接收参数x,返回x+5。

(x, y) -> x + y ,表示接收参数x和y,返回x+y的和。

lambda表达式,可以作为其他方法的参数。

::符号

可以通过 :: 来使用类的方法。

语法:

类名::方法名

比如 Integer::valueOf,就相当于Integer.valueOf()。

System.out::println,就相当于System.out.println();

Person::new,就相当于new Person();

代码示例

创建对象Worker,如下:

public class Worker {

    private String id;

    private Integer age;

    private String name;
    
    public Worker(String id, Integer age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }
    
    //getter()和setter()自行生成

二、forEach()

forEach() 方法迭代集合中的数据。

  • 遍历List:
/**
 * 遍历集合
 *
 */
public static void forEachDemo() {
    List<String> list=Arrays.asList("abc","def","","123");
    list.forEach(System.out::println);
}
  • 遍历Map:
public static void foreachTest() {
    List<Worker> list = new ArrayList<>();
    list.add(new Worker("123",18,"lin"));
    list.add(new Worker("456",28,"chen"));
    list.add(new Worker("789",38,"wu"));
    Map<String, Integer> map = new HashMap<>();
    //forEach()内的方法参数为work,执行的操作是将Worker对象的id作为key,age作为value
    list.forEach(worker -> map.put(worker.getId(),worker.getAge()));
    //遍历map,打印key和value
    // map.forEach((key,value)->System.out.println(key+","+value));
    map.forEach((key,value)-> {
            System.out.println(key+","+value);
            if ("456".equals(key)) {
                System.out.println("TargetValue:"+value);
            }
        });
}
  • 注意:

在forEach()中不能使用continue、break,即使使用return也不会终止lambda。
如下:

public static void forEachContinueTest() {
        List<Worker> list = new ArrayList<>();
        list.add(new Worker("123",18,"lin"));
        list.add(new Worker("456",28,"chen"));
        list.add(new Worker("789",38,"wu"));
        Map<String, Integer> map = new HashMap<>();
        list.forEach(worker -> map.put(worker.getId(),worker.getAge()));
        map.forEach((key,value)->{
            System.out.println(key+","+value);
            if ("456".equals(key)) {
                System.out.println("Over");
                //在forEach()中使用continue会报错"Continue outside of loop"
//                continue;   
                //在forEach()中使用return并不能中止lambda表达式
                return;      
            }
        });

    }

运行结果为:

123,18
456,28
Over
789,38

三、stream流

stream()流,可以非常方便地处理集合数据。包括filter()、map()、sorted()、forEach()等操作。

stream() − 为集合创建串行流。

parallelStream() − 为集合创建并行流。

map()

map() 方法用于映射每个元素到对应的结果

/**
 * 映射
 */
public static void mapDemo(){
    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());
    squaresList.forEach(System.out::println);
}

转换流的数据类型:

public static void mapToIntDemo() {
    List<String> numberList= Arrays.asList("3", "2","2","3");
    //将集合中的字符串转化数字,并进行加一操作,最后求和。
    int sum = numberList.stream().mapToInt(Integer::valueOf).map(x->x+1).sum();
    System.out.println(sum);
}

filter()

/**
 * 过滤
 */
public static void filterDemo(){
    List<String> list=Arrays.asList("abc","def","","123");
    //筛选出不为空的数据
    List<String> filterList = list.stream().filter(StringUtils::isNotEmpty).collect(Collectors.toList());
    filterList.forEach(System.out::println);
}

limit()

limit 方法用于获取指定数量的流。

sorted()

sorted 方法用于对流进行排序。


/**
 * 排序
 */
public static void sortedDemo() {
    List<Integer> list=Arrays.asList(1,3,5,7,2,4,6);
    List<Integer> numberList = list.stream().sorted().collect(Collectors.toList());
    numberList.forEach(System.out::println);

}

倒序输出:

/**
 * 倒序输出
 *
 */
public static void sortedReverseDemo() {
    List<Integer> list=Arrays.asList(1,3,5,7,2,4,6);
    List<Integer> numberList = list.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
    numberList.forEach(System.out::println);
}

count()

/**
 * 计数
 */
public static void countDemo() {
    List<String> list=Arrays.asList("abc","def","","123",null);
    //使用apache-common中的StringUtils,可以避免空指针
    long count = list.stream().filter(StringUtils::isNotEmpty).count();
    System.out.println(count);
}

collect()

collect() 可以将流转化为集合。

最常见的有 collect(Collectors.toList())。

还有Collectors.toMap。

/**
 *  将集合转化成符号分隔的字符串
 *
 */
public static void collectJoiningDemo(){
    List<String> list=Arrays.asList("abc","def","","123");
//      String contents=String.join(",",list);
    //表示通过 ,分隔
    String contents = list.stream().filter(StringUtils::isNotEmpty).collect(Collectors.joining(","));
    System.out.println(contents);
}

Collectors.toMap的坑

在Collectors.toMap()中,要注意:
key不可重复,否则toMap()会报错"Duplicate key"。
value不可为null,否则toMap()会报错"空指针异常"。

public static void toMapTest() {
        List<Worker> list = new ArrayList<>();
        list.add(new Worker("123",18,"lin"));
        list.add(new Worker("456",28,"chen"));
        list.add(new Worker("789",38,"wu"));
        //key不可重复,否则toMap()会报错"Duplicate key"
//        list.add(new Worker("123",18,"li"));        
        //value不可为null,否则toMap()会报错"空指针异常"
//        list.add(new Worker("000",18,null));          
        Map<String, String> map = list.stream().collect(Collectors.toMap(Worker::getId, Worker::getName));
        for (Map.Entry<String, String> entry : map.entrySet()) {
            System.out.println(entry.getKey()+","+entry.getValue());
        }
    }

参考资料:https://www.jianshu.com/p/aeb21dea87e0

reduce()

reduce在求和、求最大最小值等方面都可以很方便,注意其返回的结果是一个Optional对象:

public class StreamReduce {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
        int sum = list.stream().map( x -> x*x ).reduce( (x,y) -> x + y).get();
        System.out.println(sum);
      
//          传统的代码表现方式如下:
//          List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
//          int sum = 0;
//          for(Integer n : list) {
//              int x = n * n;
//              sum = sum + x;
//          }
//          System.out.println(sum);

    }
}

    

猜你喜欢

转载自www.cnblogs.com/expiator/p/12297003.html