Java集合操作工具:some、any以及every

最近学习PAIP的时候,顺便看了下回味了下Common Lisp,注意到几个实用的集合操作函数,本文记录下在Java中的实现。

场景

我想大家在平常开发中应该经常遇到这样场景:想要从集合中找到符合某个条件的元素,或者判断集合中是否存在某种数据,又或者是判断集合中的所有元素都符合某个要求。

针对第一种问题的基本写法是for-if-break:

Image thisImage;
for (Image image : list) {
    if (image.getId() == id) {
        thisImage = image;
        break;
    }
}
//继续使用thisImage

第二种也是类似:

boolean containsPNG = false;
for (Image image : list) {
    if (image.getType() == PNG) {
        containsPNG = true;
        break;
    }
}
//根据containsPNG进行下面操作

第三种则是:

boolean isAllPNG = true;
for (Image image : list) {
    if (image.getId() != PNG) {
        isAllPng = false;
        break;
    }
}
//根据isAllPNG进行下面操作

这几段都是简单代码,但是一个项目中可能出现多次,而且这三种情况代码非常相似,只有细节不同,但是表达的逻辑还是有很大区别,并不直白(要从代码中看出逻辑还是得花个5-10秒),没法一眼在3秒内得到代码意义。

正好Common Lisp规范中包含专门处理这类问题的标准函数,下面就来介绍下。

代码示例

首先是应对第一种情况的,我们想要找到集合中某个符合条件的元素,那么就有操作some

public void testSome() {
    List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5, 6);
    some(nums, this::isOdd).ifPresent(oddInt -> {
        //list中存在某个基数
    });
    some(images, image -> image.getId() == 0).ifPresent(invalidImage -> {
        //images中存在id为0的非法图片
    });
}

private boolean isOdd(Integer i) {
    return i % 2 == 1;
}

处理第二种“是否包含任何符合某条件的元素”情况的操作是any

List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5, 6);

boolean containsEvenNum = any(nums, i -> i % 2 == 0);//包含偶数
boolean containsPNG = any(images, image -> image.getType() == PNG);//图片列表中包含PNG
boolean notContainsNegativeNum = notAny(nums, i -> i < 0);//不包含任何负数

处理三种“是否所有元素都符合某个条件”情况的操作是every

List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5, 6);
List<String> strings = Arrays.asList("", "asdf", "1234");

boolean allNonNull = every(strings, Objects::nonNull);//所有字符串都不是null
boolean allIsPositive = every(nums, i -> i > 0);//所有数字都是整数
boolean notAllStringIsDigits = notEvery(strings, TextUtils::isDigitsOnly);//不是所有的字符串都只有数字

工具实现

some实现如下:

public static <T> Optional<T> some(Iterable<T> iterable, Predicate<? super T> predicate) {
    if (iterable != null) {
        for (T t : iterable) {
            if (predicate.test(t)) {
                return Optional.of(t);
            }
        }
    }
    return Optional.empty();
}

这里的predicate是一个断言,用来检查数据是否符合要求,比如“是偶数”就是i -> i % 2 == 0,“正整数”就是i -> i > 0。返回值是Optional形式,详细用法见相关文档。

any的实现是:

public static <T> boolean any(Iterable<T> iterable, Predicate<? super T> predicate) {
    return some(iterable, predicate).isPresent();
}

因为“是否包含任何符合条件A的元素”相当于“存在某个符合条件A的元素”,所以直接用some来实现。相对的还有否定形式的notAny

public static <T> boolean notAny(Iterable<T> iterable, Predicate<? super T> predicate) {
    return !any(iterable, predicate);
}

every的实现是:

public static <T> boolean every(Iterable<T> iterable, Predicate<? super T> predicate) {
    return !some(iterable, t -> !predicate.test(t)).isPresent();
}

因为“所有元素都满足条件A”相当于“不符合条件A的元素不存在”,所以也可以用some来实现,相对应的否定形式为notEvery

public static <T> boolean notEvery(Iterable<T> iterable, Predicate<? super T> predicate) {
    return !every(iterable, predicate);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值