Java中anyMatch()allMatch()noneMatch()用法详解

Posted 拄杖忙学轻声码

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中anyMatch()allMatch()noneMatch()用法详解相关的知识,希望对你有一定的参考价值。

说明:
anyMatch():匹配到任何一个元素和指定的元素相等,返回 true
allMatch():匹配到全部元素和指定的元素相等,返回 true
noneMatch():与 allMatch() 效果相反

验证:
一、anyMatch()

1、正常匹配,多元素

List<String> strList = ListUtil.toList("a", "b", "c", "d");
        boolean a = Optional.ofNullable(strList).orElseGet(ListUtil::toList)
                .stream()
                .anyMatch(obj -> obj.equals("a"));
        System.out.println("anyMatch()测试多元素结果:" + a);

输出:anyMatch()测试多元素结果:true

2、正常匹配,单元素

List<String> strList = ListUtil.toList("a");
        boolean a = Optional.ofNullable(strList).orElseGet(ListUtil::toList)
                .stream()
                .anyMatch(obj -> obj.equals("a"));
        System.out.println("anyMatch()测试单元素结果:" + a);

输出:anyMatch()测试单元素结果:true

正常匹配小结:
1、无论多元素还是单元素,只要匹配到任何一个元素等于 a 的都返回 true

3、取反匹配,多元素

List<String> strList = ListUtil.toList("a", "b", "c", "d");
        boolean a = Optional.ofNullable(strList).orElseGet(ListUtil::toList)
                .stream()
                .anyMatch(obj -> !obj.equals("a"));
        System.out.println("anyMatch()测试取反多元素结果:" + a);

输出:anyMatch()测试取反多元素结果:true

4、取反匹配,单元素

List<String> strList = ListUtil.toList("a");
        boolean a = Optional.ofNullable(strList).orElseGet(ListUtil::toList)
                .stream()
                .anyMatch(obj -> !obj.equals("a"));
        System.out.println("anyMatch()测试取反单元素结果:" + a);

输出:anyMatch()测试取反单元素结果:false

取反匹配小结:
1、多元素取反,任何一个元素不等于 a 的返回 true
2、单元素取反,因为是单元素只有a,没有不等于 a 的元素,所以不成立返回 false

二、allMatch()

1、匹配多元素

List<String> strList = ListUtil.toList("a", "b", "c", "d");
        boolean a = Optional.ofNullable(strList).orElseGet(ListUtil::toList)
                .stream()
                .allMatch(obj -> obj.equals("a"));
        System.out.println("allMatch()测试多元素结果:" + a);

输出:allMatch()测试多元素结果:false

2、匹配单元素

List<String> strList = ListUtil.toList("a");
        boolean a = Optional.ofNullable(strList).orElseGet(ListUtil::toList)
                .stream()
                .allMatch(obj -> obj.equals("a"));
        System.out.println("allMatch()测试单元素结果:" + a);

输出:allMatch()测试单元素结果:true

小结:
1、allMatch() 所有元素都等于指定元素返回 true
2、allMatch() 如果取反,等效于 noneMatch() 所有元素不等于指定元素返回 true

三、noneMatch()

1、匹配多元素

List<String> strList = ListUtil.toList("b", "c", "d");
        boolean a = Optional.ofNullable(strList).orElseGet(ListUtil::toList)
                .stream()
                .noneMatch(obj -> obj.equals("a"));
        System.out.println("noneMatch()测试多元素结果:" + a);

输出:noneMatch()测试多元素结果:true

2、匹配单元素

List<String> strList = ListUtil.toList("a");
        boolean a = Optional.ofNullable(strList).orElseGet(ListUtil::toList)
                .stream()
                .noneMatch(obj -> obj.equals("a"));
        System.out.println("noneMatch()测试单元素结果:" + a);

输出:noneMatch()测试单元素结果:false

小结:
1、noneMatch()所有元素都不等于指定元素返回 true 
2、noneMatch() 如果取反,等效于 allMatch() 所有元素等于指定元素返回 true

《Java8实战》 - 读书笔记 - Stream流的基本用法

第4章 引入流

  • 流是“从支持数据处理操作的源生成的一系列元素”
  • 流利用内部迭代:迭代通过filtermapsorted 等操作被抽象掉了。
  • 流操作有两类:中间操作终端操作
    • filtermap等中间操作会返回一个流,并可以链接在一起。可以用它们来设置一条流水线,但并不会生成任何结果
    • forEachcount等终端操作会返回一个非流的值,并处理流水线以返回结果
  • 流中的元素是按需计算的。
  • Stream 对应的有一套基础类型优化版如:IntStreamDoubleStreamLongStream 与这对应的各种操作也同理。详见:底部参考资料

第5章 使用流

表5-1 中间操作和终端操作

操作类型返回类型使用的类型/函数式接口函数描述符
filter中间Stream<T>Predicate<T>T -> boolean
distinct中间 (有状态-无界)Stream<T>
skip中间 (有状态-有界)Stream<T>long
limit中间 (有状态-有界)Stream<T>long
map中间Stream<R>Function<T, R>T -> R
flatMap中间Stream<R>Function<T, Stream<R>>T -> Stream<R>
sorted中间 (有状态-无界)Stream<T>Comparator<T>(T, T) -> int
anyMatch终端booleanPredicate<T>T -> boolean
noneMatch终端booleanPredicate<T>T -> boolean
allMatch终端booleanPredicate<T>T -> boolean
findAny终端Optional<T>
findFirst终端Optional<T>
forEach终端voidConsumer<T>T -> void
collect终端RCollector<T, A, R>
reduce终端 (有状态-有界)Optional<T>BinaryOperator<T>(T, T) -> T
count终端long

测试数据

@Data
@AllArgsConstructor
public class Hero
    private String name;
    private Integer age;
    private String group;

    public static List<Hero> getList()
        return Arrays.asList(
                new Hero("张三", 23, "A"), new Hero("李四", 19, "A"), new Hero("王五", 20, "B"),
                new Hero("赵六", 21, "B"), new Hero("洪七", 25, "C"), new Hero("重八", 45, "C")
        );
    

5.1 筛选和切片

筛选 filter

Stream<T> filter(Predicate<? super T> predicate);

List<Hero> heroes = Hero.getList().stream()
        .filter(hero -> hero.getAge() > 20) // 取年龄大于 20 的
        .collect(Collectors.toList());

去重 distinct

List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
numbers.stream()
        .filter(i -> i % 2 == 0) // 取偶数
        .distinct() // 去重
        .forEach(System.out::println);

截短 filter

List<Hero> heroes = Hero.getList().stream()
        .filter(hero -> hero.getAge() > 20)
        .limit(3) // 取前 3 个
        .collect(toList());
heroes.forEach(System.out::println);

跳过 skip

先丢弃前 3 个,在剩下的结果中保留前 2 个
如果想保留后两个,可以配合排序+反转

Hero.getList().stream()
        .skip(3) // 跳过前 3 个
        .limit(2) // 保留前 2 个
        .collect(toList())
        .forEach(System.out::println);

5.2 映射

映射 map

<R> Stream<R> map(Function<? super T, ? extends R> mapper);

  • 处理中每一个元素。(元素从 Hero 变成了 HeroAge
  • map 还有几个针对基础类型的优化版,直接返回基础类型流。(免于拆箱)

函数引用写法:

Hero.getList().stream()
        .map(Hero::getAge)
        .forEach(System.out::println);

Lambda写法:如果还想对年龄处理一下,可以这样

Hero.getList().stream()
         .map(hero -> hero.getAge() + "岁")
         .forEach(System.out::println);

躺平映射 flatMap

  • map:取出每个名字,拆分成数组。相当于得到一个二维数组。如:[[张, 三], [李, 四], [王, 五]]
  • Arrays::stream:接收数组创建流。
  • flatMap:将流中所有元素平铺开,放在同一个流里。如:[张, 三, 李, 四, 王, 五]
Hero.getList().stream()
        .map(hero -> hero.getName().split(""))
        .flatMap(Arrays::stream)        
        .forEach(System.out::println);

5.3 查找和匹配

查找 findAny, findFirst

这些方法利用了短路。不会傻傻的处理整个流。

方法说明
Optional<T> findFirst()返回第一个元素。
Optional<T> findAny()返回任意一个元素。

匹配 anyMatch, allMatch, noneMatch

方法说明
boolean anyMatch(Lambda)只要有一个匹配就为
boolean allMatch(Lambda)所有都匹配就为
boolean noneMatch(Lambda)所有都不匹配就为

5.4 归约

两参数版本 reduce(0, (a, c) -> a + c)

T reduce(T identity, BinaryOperator<T> accumulator);

  • 参数一:初始值。
  • 参数二:Lambda。(累计值, 当前值) -> 累计值 + 当前值
Integer sum = Hero.getList().stream()
        .map(Hero::getAge)
        .reduce(0, (a, c) -> a + c);
System.out.println("所有人加起来 " + sum + " 岁了!");

单参数版本 reduce((a, c) -> a + c)

Optional<T> reduce(BinaryOperator<T> accumulator);
默认以流中第一元素初始值

Optional<Integer> sum = Hero.getList().stream()
        .map(Hero::getAge)
        .reduce((a, c) -> a + c);
System.out.println("所有人加起来 " + sum.orElse(999) + " 岁了!");

5.5 付诸实践

略。。。

5.6 数值流

int类型数值流 mapToInt , mapToDouble, mapToLong

Double、Long 同理

映射数值流
mapToIntIntStream
mapToDoubleDoubleStream
mapToLongLongStream

转换回对象流 intStream.boxed

IntStream intStream = menu.stream().mapToInt(Dish::getCalories); 
Stream<Integer> stream = intStream.boxed();

默认值 optionalInt.orElse

如果为 null 则返回 999

OptionalInt sum = Hero.getList().stream()
        .mapToInt(Hero::getAge)
        .reduce((a, c) -> a + c);
System.out.println("所有人加起来 " + sum.orElse(999) + " 岁了!");

生成范围值 range(开始, 结束), rangeClosed(开始, 结束)

方法开始结束
public static IntStream range(int startInclusive, int endExclusive)包含不包含
public static IntStream rangeClosed(int startInclusive, int endInclusive)包含包含
IntStream intStream = IntStream.rangeClosed(1, 100);
intStream.forEach(System.out::println);

5.7 构建流

从值创建流 Stream.of

Stream.of("Java 8 ", "Lambdas ", "In ", "Action")
        .map(String::toUpperCase)
        .forEach(System.out::println);

从数组创建流 Arrays.stream

int[] numbers = 2, 3, 5, 7, 11, 13;
int sum = Arrays.stream(numbers).sum();

从文件生成流 Files.lines

java.nio.file.Files中的很多静态方法都会返回一个流。

try(Stream<String> lines = Files.lines(Paths.get("E:\\\\test.txt"), Charset.defaultCharset()))
    lines.forEach(System.out::println);

catch(IOException e) 

由函数生成无限流

无限流通常配合limit截断了来用。

迭代 Stream.iterate

接受一个初始值(在这里是0),还有一个依次应用在每个产生的新值上的Lambda(UnaryOperator类型)。

Stream.iterate(0, n -> n + 2)
	.limit(10)
	.forEach(System.out::println);

生成 Stream.generate

与iterate方法类似,generate方法也可让你按需生成一个无限流。但generate不是依次对每个新生成的值应用函数的。它接受一个Supplier类型的Lambda提供新的值。

Stream.generate(Math::random) 
	.limit(5) 
	.forEach(System.out::println);

参考资料

java.util.stream.Stream
java.util.stream.IntStream
java.util.stream.DoubleStream
java.util.stream.LongStream
java.nio.file.Files

以上是关于Java中anyMatch()allMatch()noneMatch()用法详解的主要内容,如果未能解决你的问题,请参考以下文章

精细篇Java8强大的stream API接口大全(代码优雅之道)

Groovy:java流anyMatch的模拟是啥

Java 流 - 同时具有 anyMatch 和 noneMatch 操作的目的?

JDK1.8新特性——Stream

Java 8 stream forEach filter anyMatch

如何知道java-8中的哪个元素匹配anymatch?