732

我想java.util.Collection根据谓词过滤 a 。

4

29 回答 29

785

Java 8 ( 2014 ) 在一行代码中使用流和 lambdas 解决了这个问题:

List<Person> beerDrinkers = persons.stream()
    .filter(p -> p.getAge() > 16).collect(Collectors.toList());

这是一个教程

用于Collection#removeIf就地修改集合。(注意:在这种情况下,谓词将删除满足谓词的对象):

persons.removeIf(p -> p.getAge() <= 16);

lambdaj允许在不编写循环或内部类的情况下过滤集合:

List<Person> beerDrinkers = select(persons, having(on(Person.class).getAge(),
    greaterThan(16)));

你能想象一些更具可读性的东西吗?

免责声明:我是 lambdaj 的贡献者

于 2009-09-06T13:37:49.070 回答
228

假设您使用的是Java 1.5,并且您无法添加Google Collections,我会做一些与 Google 人员所做的非常相似的事情。这与乔恩的评论略有不同。

首先将此接口添加到您的代码库中。

public interface IPredicate<T> { boolean apply(T type); }

当某个谓词对某种类型为真时,它的实现者可以回答。例如,如果TwereUserAuthorizedUserPredicate<User>implements IPredicate<T>,则AuthorizedUserPredicate#apply返回传入的是否User被授权。

然后在一些实用程序类中,你可以说

public static <T> Collection<T> filter(Collection<T> target, IPredicate<T> predicate) {
    Collection<T> result = new ArrayList<T>();
    for (T element: target) {
        if (predicate.apply(element)) {
            result.add(element);
        }
    }
    return result;
}

因此,假设您使用上述内容可能是

Predicate<User> isAuthorized = new Predicate<User>() {
    public boolean apply(User user) {
        // binds a boolean method in User to a reference
        return user.isAuthorized();
    }
};
// allUsers is a Collection<User>
Collection<User> authorizedUsers = filter(allUsers, isAuthorized);

如果线性检查的性能值得关注,那么我可能想要一个具有目标集合的域对象。具有目标集合的域对象将具有用于初始化、添加和设置目标集合的方法的过滤逻辑。

更新:

在实用程序类(比如说 Predicate)中,我添加了一个 select 方法,当谓词不返回预期值时,该方法带有一个默认值选项,以及一个用于在新 IPredicate 中使用的 params 的静态属性。

public class Predicate {
    public static Object predicateParams;

    public static <T> Collection<T> filter(Collection<T> target, IPredicate<T> predicate) {
        Collection<T> result = new ArrayList<T>();
        for (T element : target) {
            if (predicate.apply(element)) {
                result.add(element);
            }
        }
        return result;
    }

    public static <T> T select(Collection<T> target, IPredicate<T> predicate) {
        T result = null;
        for (T element : target) {
            if (!predicate.apply(element))
                continue;
            result = element;
            break;
        }
        return result;
    }

    public static <T> T select(Collection<T> target, IPredicate<T> predicate, T defaultValue) {
        T result = defaultValue;
        for (T element : target) {
            if (!predicate.apply(element))
                continue;
            result = element;
            break;
        }
        return result;
    }
}

以下示例在集合之间查找缺失的对象:

List<MyTypeA> missingObjects = (List<MyTypeA>) Predicate.filter(myCollectionOfA,
    new IPredicate<MyTypeA>() {
        public boolean apply(MyTypeA objectOfA) {
            Predicate.predicateParams = objectOfA.getName();
            return Predicate.select(myCollectionB, new IPredicate<MyTypeB>() {
                public boolean apply(MyTypeB objectOfB) {
                    return objectOfB.getName().equals(Predicate.predicateParams.toString());
                }
            }) == null;
        }
    });

以下示例在集合中查找实例,并在未找到该实例时将集合的第一个元素作为默认值返回:

MyType myObject = Predicate.select(collectionOfMyType, new IPredicate<MyType>() {
public boolean apply(MyType objectOfMyType) {
    return objectOfMyType.isDefault();
}}, collectionOfMyType.get(0));

更新(Java 8 发布后):

自从我(艾伦)第一次发布这个答案以来已经有好几年了,我仍然不敢相信我正在为这个答案收集 SO 积分。无论如何,既然 Java 8 已经为该语言引入了闭包,那么我的答案现在会大不相同,而且更简单。使用 Java 8,不需要一个独特的静态实用程序类。因此,如果您想找到与谓词匹配的第一个元素。

final UserService userService = ... // perhaps injected IoC
final Optional<UserModel> userOption = userCollection.stream().filter(u -> {
    boolean isAuthorized = userService.isAuthorized(u);
    return isAuthorized;
}).findFirst();

用于选项的 JDK 8 API 能够使用get()isPresent()、和orElse(defaultUser),以及其他“单子”函数,例如、和。orElseGet(userSupplier)orElseThrow(exceptionSupplier)mapflatMapfilter

如果您只想收集与谓词匹配的所有用户,则使用Collectors终止所需集合中的流。

final UserService userService = ... // perhaps injected IoC
final List<UserModel> userOption = userCollection.stream().filter(u -> {
    boolean isAuthorized = userService.isAuthorized(u);
    return isAuthorized;
}).collect(Collectors.toList());

有关 Java 8 流如何工作的更多示例,请参见此处

于 2008-09-23T16:41:41.417 回答
93

使用来自 Apache Commons 的CollectionUtils.filter(Collection,Predicate) 。

于 2008-09-23T16:28:43.867 回答
68

“最佳”方式的要求太宽泛了。它是“最短的”吗?“最快的”?“可读”?过滤就地或进入另一个集合?

最简单(但不是最易读)的方法是迭代它并使用 Iterator.remove() 方法:

Iterator<Foo> it = col.iterator();
while( it.hasNext() ) {
  Foo foo = it.next();
  if( !condition(foo) ) it.remove();
}

现在,为了使其更具可读性,您可以将其包装到实用程序方法中。然后发明一个 IPredicate 接口,创建该接口的匿名实现并执行以下操作:

CollectionUtils.filterInPlace(col,
  new IPredicate<Foo>(){
    public boolean keepIt(Foo foo) {
      return foo.isBar();
    }
  });

其中 filterInPlace() 迭代集合并调用 Predicate.keepIt() 以了解实例是否保留在集合中。

我真的不认为有理由为这项任务引入第三方库。

于 2008-09-23T16:41:32.557 回答
62

考虑Google Collections以获得支持泛型的更新的 Collections 框架。

更新:谷歌收藏库现已弃用。您应该改用最新版本的Guava。它仍然具有对集合框架的所有相同扩展,包括基于谓词的过滤机制。

于 2008-09-23T16:29:49.090 回答
31

等待 Java 8:

List<Person> olderThan30 = 
  //Create a Stream from the personList
  personList.stream().
  //filter the element to select only those with age >= 30
  filter(p -> p.age >= 30).
  //put those filtered elements into a new List.
  collect(Collectors.toList());
于 2013-08-29T10:50:37.110 回答
11

从 Java 8 的早期版本开始,您可以尝试以下操作:

Collection<T> collection = ...;
Stream<T> stream = collection.stream().filter(...);

例如,如果您有一个整数列表,并且想要过滤大于 10 的数字,然后将这些数字打印到控制台,您可以执行以下操作:

List<Integer> numbers = Arrays.asList(12, 74, 5, 8, 16);
numbers.stream().filter(n -> n > 10).forEach(System.out::println);
于 2013-10-27T21:41:55.647 回答
11

我将把RxJava 扔进戒指,它也可以在Android上使用。RxJava 可能并不总是最好的选择,但如果您希望在您的集合上添加更多转换或在过滤时处理错误,它将为您提供更大的灵活性。

Observable.from(Arrays.asList(1, 2, 3, 4, 5))
    .filter(new Func1<Integer, Boolean>() {
        public Boolean call(Integer i) {
            return i % 2 != 0;
        }
    })
    .subscribe(new Action1<Integer>() {
        public void call(Integer i) {
            System.out.println(i);
        }
    });

输出:

1
3
5

更多关于 RxJava 的细节filter可以在这里找到。

于 2014-07-24T02:13:01.357 回答
7

您确定要过滤 Collection 本身,而不是迭代器吗?

org.apache.commons.collections.iterators.FilterIterator

或使用版本 4 的 apache commons org.apache.commons.collections4.iterators.FilterIterator

于 2008-09-23T16:41:08.207 回答
7

设置:

public interface Predicate<T> {
  public boolean filter(T t);
}

void filterCollection(Collection<T> col, Predicate<T> predicate) {
  for (Iterator i = col.iterator(); i.hasNext();) {
    T obj = i.next();
    if (predicate.filter(obj)) {
      i.remove();
    }
  }
}

用法:

List<MyObject> myList = ...;
filterCollection(myList, new Predicate<MyObject>() {
  public boolean filter(MyObject obj) {
    return obj.shouldFilter();
  }
});
于 2008-09-23T16:41:27.067 回答
7

让我们看看如何使用Eclipse Collections过滤内置的 JDK List 和MutableList

List<Integer> jdkList = Arrays.asList(1, 2, 3, 4, 5);
MutableList<Integer> ecList = Lists.mutable.with(1, 2, 3, 4, 5);

如果您想过滤小于 3 的数字,您会期望得到以下输出。

List<Integer> selected = Lists.mutable.with(1, 2);
List<Integer> rejected = Lists.mutable.with(3, 4, 5);

以下是使用 Java 8 lambda 作为Predicate.

Assert.assertEquals(selected, Iterate.select(jdkList, each -> each < 3));
Assert.assertEquals(rejected, Iterate.reject(jdkList, each -> each < 3));

Assert.assertEquals(selected, ecList.select(each -> each < 3));
Assert.assertEquals(rejected, ecList.reject(each -> each < 3));

以下是使用匿名内部类作为Predicate.

Predicate<Integer> lessThan3 = new Predicate<Integer>()
{
    public boolean accept(Integer each)
    {
        return each < 3;
    }
};

Assert.assertEquals(selected, Iterate.select(jdkList, lessThan3));
Assert.assertEquals(selected, ecList.select(lessThan3));

以下是使用Predicates工厂过滤 JDK 列表和Eclipse Collections MutableLists的一些替代方法。

Assert.assertEquals(selected, Iterate.select(jdkList, Predicates.lessThan(3)));
Assert.assertEquals(selected, ecList.select(Predicates.lessThan(3)));

这是一个不为谓词分配对象的版本,通过使用Predicates2工厂而不是selectWith采用Predicate2.

Assert.assertEquals(
    selected, ecList.selectWith(Predicates2.<Integer>lessThan(), 3));

有时你想过滤一个否定的条件。Eclipse Collections 中有一个特殊的方法,叫做reject.

Assert.assertEquals(rejected, Iterate.reject(jdkList, lessThan3));
Assert.assertEquals(rejected, ecList.reject(lessThan3));

该方法partition将返回两个集合,其中包含由 选择和拒绝的元素Predicate

PartitionIterable<Integer> jdkPartitioned = Iterate.partition(jdkList, lessThan3);
Assert.assertEquals(selected, jdkPartitioned.getSelected());
Assert.assertEquals(rejected, jdkPartitioned.getRejected());

PartitionList<Integer> ecPartitioned = gscList.partition(lessThan3);
Assert.assertEquals(selected, ecPartitioned.getSelected());
Assert.assertEquals(rejected, ecPartitioned.getRejected());

注意:我是 Eclipse Collections 的提交者。

于 2012-09-24T22:28:48.597 回答
7

一些简单明了的 Java 怎么样?

 List<Customer> list ...;
 List<Customer> newList = new ArrayList<>();
 for (Customer c : list){
    if (c.getName().equals("dd")) newList.add(c);
 }

简单、易读且容易(并且可以在 Android 中使用!)但是如果您使用的是 Java 8,您可以通过简单的一行代码来实现:

List<Customer> newList = list.stream().filter(c -> c.getName().equals("dd")).collect(toList());

注意 toList() 是静态导入的

于 2014-05-12T05:03:57.270 回答
5

Google 的 Guava 库中的Collections2.filter(Collection,Predicate)方法可以满足您的需求。

于 2008-09-23T18:21:13.253 回答
5

使用 ForEach DSL,您可以编写

import static ch.akuhn.util.query.Query.select;
import static ch.akuhn.util.query.Query.$result;
import ch.akuhn.util.query.Select;

Collection<String> collection = ...

for (Select<String> each : select(collection)) {
    each.yield = each.value.length() > 3;
}

Collection<String> result = $result();

给定一个 [The, quick, brown, fox, jumps, over, the,lazy, dog] 的集合,这将导致 [quick, brown, jumps, over, lazy],即所有长度超过三个字符的字符串。

ForEach DSL 支持的所有迭代样式都是

  • AllSatisfy
  • AnySatisfy
  • Collect
  • Counnt
  • CutPieces
  • Detect
  • GroupedBy
  • IndexOf
  • InjectInto
  • Reject
  • Select

更多详情请参考https://www.iam.unibe.ch/scg/svn_repos/Sources/ForEach

于 2008-12-03T13:45:55.703 回答
5

由于启用了 java 9 : Collectors.filtering

public static <T, A, R>
    Collector<T, ?, R> filtering(Predicate<? super T> predicate,
                                 Collector<? super T, A, R> downstream)

因此过滤应该是:

collection.stream().collect(Collectors.filtering(predicate, collector))

例子:

List<Integer> oddNumbers = List.of(1, 19, 15, 10, -10).stream()
            .collect(Collectors.filtering(i -> i % 2 == 1, Collectors.toList()));
于 2018-05-24T13:59:00.170 回答
3

这一点,再加上缺乏真正的闭包,是我对 Java 最大的抱怨。老实说,上面提到的大多数方法都非常容易阅读并且非常有效。然而,在花时间使用 .Net、Erlang 等之后......在语言级别集成的列表理解使一切变得更加清晰。如果没有语言级别的添加,Java 就不能像该领域的许多其他语言一样干净。

如果性能是一个巨大的问题,谷歌集合是要走的路(或编写自己的简单谓词实用程序)。Lambdaj 语法对某些人来说更具可读性,但效率不高。

然后是我写的一个库。我会忽略任何关于它的效率的问题(是的,它很糟糕)......是的,我清楚地知道它是基于反射的,不,我实际上并没有使用它,但它确实有效:

LinkedList<Person> list = ......
LinkedList<Person> filtered = 
           Query.from(list).where(Condition.ensure("age", Op.GTE, 21));

或者

LinkedList<Person> list = ....
LinkedList<Person> filtered = Query.from(list).where("x => x.age >= 21");
于 2010-01-21T04:35:30.130 回答
2

我编写了一个扩展的 Iterable 类,它支持在不复制集合内容的情况下应用功能算法。

用法:

List<Integer> myList = new ArrayList<Integer>(){ 1, 2, 3, 4, 5 }

Iterable<Integer> filtered = Iterable.wrap(myList).select(new Predicate1<Integer>()
{
    public Boolean call(Integer n) throws FunctionalException
    {
        return n % 2 == 0;
    }
})

for( int n : filtered )
{
    System.out.println(n);
}

上面的代码将实际执行

for( int n : myList )
{
    if( n % 2 == 0 ) 
    {
        System.out.println(n);
    }
}
于 2010-04-05T12:43:11.587 回答
2

JFilter http://code.google.com/p/jfilter/最适合您的要求。

JFilter 是一个用于查询 Java bean 集合的简单且高性能的开源库。

主要特点

  • 支持集合(java.util.Collection、java.util.Map 和 Array)属性。
  • 支持任意深度的集合内集合。
  • 支持内部查询。
  • 支持参数化查询。
  • 可以在 100 毫秒内过滤 100 万条记录。
  • 过滤器(查询)以简单的 json 格式给出,类似于 Mangodb 查询。以下是一些例子。
  • { "id":{"$le":"10"}
    • 其中对象 id 属性小于等于 10。
  • { "id": {"$in":["0", "100"]}}
    • 其中对象 id 属性为 0 或 100。
  • {"lineItems":{"lineAmount":"1"}}
    • 其中参数化类型的 lineItems 集合属性的 lineAmount 等于 1。
  • { "$and":[{"id":"0"}, {"billingAddress":{"city":"DEL"}}]}
    • 其中 id 属性为 0,而 billingAddress.city 属性为 DEL。
  • {"lineItems":{"taxes":{ "key":{"code":"GST"}, "value":{"$gt":"1.01"}}}}
    • 其中参数化类型的 lineItems 集合属性具有参数化类型的税收地图类型属性的代码等于大于 1.01 的 GST 值。
  • {'$or':[{'code':'10'},{'skus': {'$and':[{'price':{'$in':['20', '40']} }, {'code':'RedApple'}]}}]}
    • 选择产品代码为 10 或 sku 价格为 20 和 40 且 sku 代码为“RedApple”的所有产品。
于 2012-04-05T10:46:58.387 回答
2

使用集合查询引擎(CQEngine)。这是迄今为止最快的方法。

另请参阅:如何在 Java 中查询对象集合(Criteria/SQL-like)?

于 2012-07-29T22:12:45.320 回答
2

这里有一些非常棒的答案。我,我想保持尽可能简单和可读:

public abstract class AbstractFilter<T> {

    /**
     * Method that returns whether an item is to be included or not.
     * @param item an item from the given collection.
     * @return true if this item is to be included in the collection, false in case it has to be removed.
     */
    protected abstract boolean excludeItem(T item);

    public void filter(Collection<T> collection) {
        if (CollectionUtils.isNotEmpty(collection)) {
            Iterator<T> iterator = collection.iterator();
            while (iterator.hasNext()) {
                if (excludeItem(iterator.next())) {
                    iterator.remove();
                }
            }
        }
    }
}
于 2015-01-07T11:07:38.423 回答
2

使用java 8, 具体来说lambda expression,您可以像下面的示例一样简单地执行此操作:

myProducts.stream().filter(prod -> prod.price>10).collect(Collectors.toList())

where 对于每个product内部myProducts集合,如果prod.price>10,则将此产品添加到新的过滤列表中。

于 2015-12-12T21:47:55.503 回答
2

在 Java 8 中,您可以直接使用此过滤器方法,然后执行此操作。

 List<String> lines = Arrays.asList("java", "pramod", "example");

 List<String> result = lines.stream()              
         .filter(line -> !"pramod".equals(line))     
         .collect(Collectors.toList());              

 result.forEach(System.out::println); 
于 2018-10-18T13:40:04.420 回答
1

简单的 pre-Java8 解决方案:

ArrayList<Item> filtered = new ArrayList<Item>(); 
for (Item item : items) if (condition(item)) filtered.add(item);

不幸的是,这个解决方案不是完全通用的,输出一个列表而不是给定集合的类型。此外,除非条件很复杂,否则引入库或编写包装此代码的函数对我来说似乎有点矫枉过正,但是您可以为该条件编写一个函数。

于 2014-07-03T18:54:39.753 回答
1

https://code.google.com/p/joquery/

支持不同的可能性,

给定收藏,

Collection<Dto> testList = new ArrayList<>();

类型,

class Dto
{
    private int id;
    private String text;

    public int getId()
    {
        return id;
    }

    public int getText()
    {
        return text;
    }
}

筛选

爪哇 7

Filter<Dto> query = CQ.<Dto>filter(testList)
    .where()
    .property("id").eq().value(1);
Collection<Dto> filtered = query.list();

爪哇 8

Filter<Dto> query = CQ.<Dto>filter(testList)
    .where()
    .property(Dto::getId)
    .eq().value(1);
Collection<Dto> filtered = query.list();

还,

Filter<Dto> query = CQ.<Dto>filter()
        .from(testList)
        .where()
        .property(Dto::getId).between().value(1).value(2)
        .and()
        .property(Dto::grtText).in().value(new string[]{"a","b"});

排序(也可用于 Java 7)

Filter<Dto> query = CQ.<Dto>filter(testList)
        .orderBy()
        .property(Dto::getId)
        .property(Dto::getName)
    Collection<Dto> sorted = query.list();

分组(也可用于 Java 7)

GroupQuery<Integer,Dto> query = CQ.<Dto,Dto>query(testList)
        .group()
        .groupBy(Dto::getId)
    Collection<Grouping<Integer,Dto>> grouped = query.list();

联接(也可用于 Java 7)

鉴于,

class LeftDto
{
    private int id;
    private String text;

    public int getId()
    {
        return id;
    }

    public int getText()
    {
        return text;
    }
}

class RightDto
{
    private int id;
    private int leftId;
    private String text;

    public int getId()
    {
        return id;
    }

    public int getLeftId()
        {
            return leftId;
        }

    public int getText()
    {
        return text;
    }
}

class JoinedDto
{
    private int leftId;
    private int rightId;
    private String text;

    public JoinedDto(int leftId,int rightId,String text)
    {
        this.leftId = leftId;
        this.rightId = rightId;
        this.text = text;
    }

    public int getLeftId()
    {
        return leftId;
    }

    public int getRightId()
        {
            return rightId;
        }

    public int getText()
    {
        return text;
    }
}

Collection<LeftDto> leftList = new ArrayList<>();

Collection<RightDto> rightList = new ArrayList<>();

可以加入喜欢,

Collection<JoinedDto> results = CQ.<LeftDto, LeftDto>query().from(leftList)
                .<RightDto, JoinedDto>innerJoin(CQ.<RightDto, RightDto>query().from(rightList))
                .on(LeftFyo::getId, RightDto::getLeftId)
                .transformDirect(selection ->  new JoinedDto(selection.getLeft().getText()
                                                     , selection.getLeft().getId()
                                                     , selection.getRight().getId())
                                 )
                .list();

表达式

Filter<Dto> query = CQ.<Dto>filter()
    .from(testList)
    .where()
    .exec(s -> s.getId() + 1).eq().value(2);
于 2014-09-03T12:59:35.897 回答
1

CollectionUtils我的答案建立在 Kevin Wong 的基础上,这里是使用from spring和 Java 8 lambda表达式的单行代码。

CollectionUtils.filter(list, p -> ((Person) p).getAge() > 16);

这与我见过的任何替代方法一样简洁易读(不使用基于方面的库)

Spring CollectionUtils从 spring 版本 4.0.2.RELEASE 开始可用,记住你需要 JDK 1.8 和语言级别 8+。

于 2015-04-22T11:18:24.310 回答
1

我需要根据列表中已经存在的值过滤列表。例如,删除所有小于当前值的值。{2 5 3 4 7 5} -> {2 5 7}。或者例如删除所有重复项 {3 5 4 2 3 5 6} -> {3 5 4 2 6}。

public class Filter {
    public static <T> void List(List<T> list, Chooser<T> chooser) {
        List<Integer> toBeRemoved = new ArrayList<>();
        leftloop:
        for (int right = 1; right < list.size(); ++right) {
            for (int left = 0; left < right; ++left) {
                if (toBeRemoved.contains(left)) {
                    continue;
                }
                Keep keep = chooser.choose(list.get(left), list.get(right));
                switch (keep) {
                    case LEFT:
                        toBeRemoved.add(right);
                        continue leftloop;
                    case RIGHT:
                        toBeRemoved.add(left);
                        break;
                    case NONE:
                        toBeRemoved.add(left);
                        toBeRemoved.add(right);
                        continue leftloop;
                }
            }
        }

        Collections.sort(toBeRemoved, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });

        for (int i : toBeRemoved) {
            if (i >= 0 && i < list.size()) {
                list.remove(i);
            }
        }
    }

    public static <T> void List(List<T> list, Keeper<T> keeper) {
        Iterator<T> iterator = list.iterator();
        while (iterator.hasNext()) {
            if (!keeper.keep(iterator.next())) {
                iterator.remove();
            }
        }
    }

    public interface Keeper<E> {
        boolean keep(E obj);
    }

    public interface Chooser<E> {
        Keep choose(E left, E right);
    }

    public enum Keep {
        LEFT, RIGHT, BOTH, NONE;
    }
}

这将像这样使用。

List<String> names = new ArrayList<>();
names.add("Anders");
names.add("Stefan");
names.add("Anders");
Filter.List(names, new Filter.Chooser<String>() {
    @Override
    public Filter.Keep choose(String left, String right) {
        return left.equals(right) ? Filter.Keep.LEFT : Filter.Keep.BOTH;
    }
});
于 2017-06-15T14:28:05.380 回答
1

就我而言,我正在寻找排除特定字段 null 的列表。这可以通过 for 循环来完成,并填充没有空地址的对象的临时列表。但感谢 Java 8 Streams

List<Person> personsList = persons.stream()
.filter(p -> p.getAdrress() != null).collect(Collectors.toList());

#java #collection #collections #java8 #streams

于 2021-07-27T14:56:00.407 回答
0

与番石榴:

Collection<Integer> collection = Lists.newArrayList(1, 2, 3, 4, 5);

Iterators.removeIf(collection.iterator(), new Predicate<Integer>() {
    @Override
    public boolean apply(Integer i) {
        return i % 2 == 0;
    }
});

System.out.println(collection); // Prints 1, 3, 5
于 2016-12-15T09:20:47.887 回答
0

Java 集合流的替代(更轻量级)替代方案是 Ocl.java 库,它使用 vanilla 集合和 lambda:https ://github.com/eclipse/agileuml/blob/master/Ocl.java

例如,ArrayList 单词的简单过滤器和求和可以是:

ArrayList<Word> sel = Ocl.selectSequence(words, 
                             w -> w.pos.equals("NN")); 
int total = Ocl.sumint(Ocl.collectSequence(sel,
                             w -> w.text.length())); 

其中 Word 有字符串 pos;字符串文本;属性。效率似乎类似于流选项,例如,两个版本在大约 50 毫秒内处理 10000 个单词。

Python、Swift 等有等效的 OCL 库。基本上,Java 集合流重新发明了 OCL 操作 ->select、->collect 等,这些操作自 1998 年以来就存在于 OCL 中。

于 2021-10-03T10:26:42.190 回答