【问题标题】:Filtering List using Java8 streams使用 Java8 流过滤列表
【发布时间】:2020-05-25 14:55:29
【问题描述】:

我有一个客户对象列表如下:

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

public class CheckForResource {

    public static void main(String[] args) {
        Customer john = new Customer("111", "P_1", "daily",
                "create", "table_1", "03-05-2020",
                "03-05-2020", "140");

        Customer mary = new Customer("111", "P_1", "daily",
                "delete", "table_1", "03-05-2020",
                "03-05-2020", "30");

        Customer joseph = new Customer("222", "P_2", "weekly",
                "create", "table_2", "03-05-2020",
                "03-05-2020", "50");

        Customer jason = new Customer("222", "P_2", "daily",
                "update", "table_2", "03-05-2020",
                "03-05-2020", "40");

        Customer mario = new Customer("111", "P_1", "weekly",
                "create", "table_1", "03-05-2020",
                "03-05-2020", "20");

        Customer danny = new Customer("111", "P_1", "monthly",
                "update", "table_1", "03-05-2020",
                "03-05-2020", "100");

        List<CheckForResource.Customer> customers = Arrays.asList(john, mary, joseph, jason, mario, danny);

    }


    public static class Customer {

        final String Id;
        final String pCode;
        final String usageType;
        final String operation;
        final String resource; 
        final String startTime;
        final String endTime;
        final String value;

        public Customer(String id, String pCode, String usageType, String operation,
                        String resource, String startTime, String endTime, String value) {
            Id = id;
            this.pCode = pCode;
            this.usageType = usageType;
            this.operation = operation;
            this.resource = resource;
            this.startTime = startTime;
            this.endTime = endTime;
            this.value = value;
        }
    }
}

如果列表具有以下每个子句的至少 1 个条目,我想返回 true

  1. customerId="111", operation="create", usageType="daily"
  2. customerId="111", operation="create", usageType="monthly"
  3. customerId="111", operation="delete", usageType="daily"
  4. customerId="111", operation="delete", usageType="monthly"
  5. customerId="111", operation="update", usageType="daily"
  6. customerId="111", operation="update", usageType="monthly"

如何使用 Steam 实现这一点?

【问题讨论】:

  • 你的条件可以简化为"111".equals(customer.getId()) &amp;&amp; ("create".equals(customer.getOperation()) || "delete".equals(customer.getOperation())) &amp;&amp; ("daily".equals(customer.getUsageType()) || "monthly".equals(customer.getUsageType()))。如果您要创建多个 Predicate 实例,您仍然可以使用 or() 组合它们
  • @ernest_k 这个解决方案不起作用列表没有条目,比如说 customerId="111", operation="update", usageType="monthly"
  • 我想你错过了我在括号内使用||这一事实。
  • @ernest_k 我试过这个。如果列表没有第 6 条的条目,则 Predicate p1 = c -> "111".equals(c.getId()) && ("create".equals(c.getOperation()) || "删除".equals(c.getOperation())) && ("daily".equals(c.getUsageType()) || "monthly".equals(c.getUsageType()));仍然返回 true
  • 我认为您需要澄清您的问题。我的理解是,如果列表中的至少一个元素满足 6 个条件中的至少一个,您就想返回 true。但是您改为检查每个条件是否由至少一个元素满足。不是很清楚。

标签: java java-stream


【解决方案1】:

您可以使用.anyMatch()

Predicate<Customer> p = c -> c.getId().equals("111") &&
                        (c.getUsageType().equals("daily") || c.getUsageType().equals("monthly")) &&
                        (c.getOperation().equals("create") || c.getOperation().equals("delete") || c.getOperation().equals("update"));
boolean result = customers.stream().filter(p)
                          .map(c -> c.getId().concat(c.getOperation()).concat(c.getUsageType()))  // Map to create hash string for detect unique
                          .distinct().count() == 6;  // distinct and check the count.

【讨论】:

  • 我有多个谓词。我可以用多个谓词来实现这一点
  • 因为我有 6 个子句,它会是谓词列表吗?
  • 答案已更新。您可以在一个谓词中使用多个 and/or
  • 我尝试了您的解决方案。如果列表没有条目让我们说 customerId="111", operation="update", usageType="monthly",它将不起作用
  • 如果列表中的每个子句都有一个条目,我想返回 true
【解决方案2】:

试试这样:

  • 过滤掉 id == 111 后,您有六种不同的可能性。
  • 因此,如果您构建谓词列表,您可以执行以下操作
  • 如果您有六个条目,则它满足条件。

根据operationusageType 创建谓词列表

List<Predicate<String>> preds = toPredicateList(
        new String[] { "create", "delete", "update" },
        new String[] { "daily", "monthly"});

判断是否满足条件。

boolean result = 
        customers
            .stream()
            .filter(c -> c.Id.equals("111"))
            .map(c -> c.operation + c.usageType)
            .filter(preds.stream().reduce(k -> false,
                                Predicate::or))
            .collect(Collectors.toSet()).size() == 6;

System.out.println(result);

构造谓词列表

public List<Predicate<String>> toPredicateList(String[] ops,
            String[] types) {

        List<Predicate<String>> list = new ArrayList<>();
        for (String o : ops) {
            for (String t : types) {
                list.add(s -> s.equals(o + t));
            }
        }
    }
    return list;
}

【讨论】:

  • 你怎么知道使用类型和操作是 OP 正在寻找的?
  • 是的,但是您计算的是 6 个任意值,而不是检查这些值是每天创建、每月删除等等。可能有一个 insertyearly 或任何我们所知道的
  • 根据您的观察修改答案。
猜你喜欢
  • 2019-12-07
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多