Lambda中常用流操作

得意时要看淡,失意时要看开。不论得意失意,切莫大意;不论成功失败,切莫止步。志得意满时,需要的是淡然,给自己留一条退路;失意落魄时,需要的是泰然,给自己觅一条出路Lambda中常用流操作,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

Java 8 中对核心类库的改进主要包括集合类的 API 和新引入的流 (Stream)。流使程序员得以站在更高的抽象层次上对集合进行操作。

迭代

从外部迭代到内部迭代。

外部迭代

首先调用 iterator 方法,产生一个新的 Iterator 对象,进而控制整个迭代过程,这就是外部迭代
迭代过程通过显式调用 Iterator 对象的 hasNext 和 next 方法完成迭代。
for 循环其实是一个封装了迭代的语法糖。

内部迭代

stream() 方法的调用,该方法不是返回一个控制迭代的 Iterator 对象,而是返 回内部迭代中的相应接口:Stream。
使用stream() 方法,就是内部迭代

实现机制

long count = list.stream().filter(e -> e.getName().equals("a")).count();

这行代码并未做什么实际性的工作,filter 只刻画出了 Stream,但没有产生新的集合。
像 filter 这样只描述 Stream,最终不产生新集合的方法叫作惰性求值方法;而像 count 这样 最终会从 Stream 产生值的方法叫作及早求值方法

判断一个操作是惰性求值还是及早求值?
只需看它的返回值。如果返回值是 Stream, 那么是惰性求值;
如果返回值是另一个值或为空,那么就是及早求值。

使用这些操作的理想方式就是形成一个惰性求值的链,最后用一个及早求值的操作返回想要的结果,这正是它的合理之处。计数的示例也是这样运行的,但这只是最简单的情况:只含两步操作。

常用的流方法

具体的可以看下Stream类中的方法。

collect(toList())

collect(toList()) 方法由 Stream 里的值生成一个列表,是一个及早求值操作。

List<String> collected = Stream.of("a", "b", "c").collect(Collectors.toList());

这段程序展示了如何使用 collect(toList()) 方法从 Stream 中生成一个列表。

map

如果有一个函数可以将一种类型的值转换成另外一种类型,map 操作就可以 使用该函数,将一个流中的值转换成一个新的流。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;


public class MapTest {

    public static void main(String[] args) {
        List<String> collected = new ArrayList<>();

        for (String string : Arrays.asList("a", "b", "hello")) {
            String uppercaseString = string.toUpperCase();
            collected.add(uppercaseString);
        }
        System.out.println(collected);


        List<String> collected1 = Stream.of("a", "b", "hello")
                .map(e -> e.toUpperCase())
                .collect(Collectors.toList());
        System.out.println(collected1);
    }
}

传给 map 的 Lambda 表达式只接受一个 String 类型的参数,返回一个新的 String。参数 和返回值不必属于同一种类型,但是 Lambda 表达式必须是 Function 接口的一个实例,Function 接口是只包含一个参数的普通函数接口。

filter

遍历数据并检查其中的元素时,可尝试使用 Stream 中提供的新方法 filter

long count = list.stream().filter(e -> e.getName().equals("a")).count();

filter 接受一个函数作为参数,该函数用 Lambda 表达式表示。
其返回值肯定是 true 或者 false。经过过滤, Stream 中符合条件的,即 Lambda 表达式值为 true 的元素被保留下来。该 Lambda 表达式 的函数接口就是 Predicate接口。

flatMap

flatMap 方法可用 Stream 替换值,然后将多个 Stream 连接成一个 Stream

List<Integer> together = Stream.of(Arrays.asList(1, 2), Arrays.asList(3, 4))
                .flatMap(numbers -> numbers.stream())
                .collect(Collectors.toList());
        System.out.println(together);

List<Integer> together1 = Stream.of(Arrays.asList(1, 2), Arrays.asList(3, 4))
                .flatMap(Collection::stream) //方法引用
                .collect(Collectors.toList());
        System.out.println(together1);

调用 stream 方法,将每个列表转换成 Stream 对象,其余部分由 flatMap 方法处理。 flatMap 方法的相关函数接口和 map 方法的一样,都是 Function 接口,只是方法的返回值 限定为 Stream 类型罢了。

max和min

Stream 上常用的操作之一是求最大值和最小值。

List<Person> persons = Arrays.asList(new Person("a", 20),
                new Person("b", 30),
                new Person("c", 40));
        Optional<Person> young = persons.stream().min(Comparator.comparing(Person::getAge));
        young.ifPresent(System.out::println);

需要传给它一个 Comparator 对象。Java 8 提 供了一个新的静态方法 comparing,使用它可以方便地实现一个比较器。(实际上这个方法接受一个函数并返回另一个函数。)

reduce

reduce 操作可以实现从一组值中生成一个值。在上述例子中用到的 count、min 和 max 方 法,因为常用而被纳入标准库中。事实上,这些方法都是 reduce 操作。

int count = Stream.of(1, 2, 3)
                .reduce(0, (acc, element) -> acc + element);
// Lambda 表达式的返回值是最新的 acc,是上一轮 acc 的值和当前元素相加的结果。

System.out.println(count);
// 输出:6

Lambda 表达式就是 reducer,它执行求和操作,有两个 参数:传入 Stream 中的当前元素和 acc。将两个参数相加,acc 是累加器,保存着当前的 累加结果。

// 可以将 reduce 操作展开
BinaryOperator<Integer> accumulator = (acc, element) -> acc + element;
int count1 = accumulator
                .apply(accumulator.apply(accumulator.apply(0, 1), 2), 3);

System.out.println(count1);

常用实例

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class LambdaTest {

    public static void main(String[] args) {
        List<Person> personList = Arrays.asList(
                new Person("a", 20),
                new Person("b", 30),
                new Person("c", 20));
	}
}

以某个属性分组

Map<Integer, List<Person>> map = personList.stream().collect(Collectors.groupingBy(Person::getAge));

获取集合中的某个属性转为集合

List<String> list = personList.stream().map(Person::getName).collect(Collectors.toList());

根据集合中的某个属性进行升序重排

List<Person> personList1 = personList.stream().sorted(Comparator.comparing(Person::getAge)).collect(Collectors.toList());

根据集合中的某个属性进行降序重排

List<Person> personList2 = personList.stream().sorted(Comparator.comparing(Person::getAge).reversed()).collect(Collectors.toList());

集合中的属性去重

List<Integer> integerList = Arrays.asList(1, 2, 3, 2, 4, 3).stream().distinct().collect(Collectors.toList());

list集合本身以某个属性作为目标去重

ArrayList<Person> collect = personList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Person::getAge))), ArrayList::new));

根据集合中的某个属性过滤并获取第一个

Person person = personList.stream().filter(e -> e.getAge() == 20).findFirst().orElse(null);

根据集合中的属性转换为键值对Map

注意,不允许有重复key,存在重复key时会报错

Map<String, Person> personMap = personList.stream().collect(Collectors.toMap(Person::getName, e -> e));

获取集合中某个最大值的int数据

int i = personList.stream().mapToInt(Person::getAge).max().orElse(-1);

计算总数

int sum = personList.stream().mapToInt(Person::getAge).sum();

将List转换为List

List<Integer> intList = new ArrayList<>();
intList.add(1);
intList.add(3);
intList.add(4);
List<String> stringList = intList.stream().map(String::valueOf).collect(Collectors.toList());

List<Integer> integers = Arrays.asList(1, 2, 3, 4);
List<String> strings = integers.stream().map(x -> x + "").collect(Collectors.toList());

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之家整理,本文链接:https://www.bmabk.com/index.php/post/155648.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之家——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!