当前位置: 首页 > 知识库问答 >
问题:

将Java流筛选为1个且仅为1个元素

路金鑫
2023-03-14

我正在尝试使用Java 8streams来查找linkedlist中的元素。但是,我想保证只有一个和筛选条件匹配。

取此代码:

public static void main(String[] args) {

    LinkedList<User> users = new LinkedList<>();
    users.add(new User(1, "User1"));
    users.add(new User(2, "User2"));
    users.add(new User(3, "User3"));

    User match = users.stream().filter((user) -> user.getId() == 1).findAny().get();
    System.out.println(match.toString());
}
static class User {

    @Override
    public String toString() {
        return id + " - " + username;
    }

    int id;
    String username;

    public User() {
    }

    public User(int id, String username) {
        this.id = id;
        this.username = username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public int getId() {
        return id;
    }
}

代码根据用户的ID查找他们。但不能保证有多少user与筛选器匹配。

将筛选器行更改为:

User match = users.stream().filter((user) -> user.getId() < 0).findAny().get();

将抛出nosuchelementexception(好!)

但是,如果有多个匹配,我希望它抛出一个错误。有办法做到这一点吗?

共有1个答案

伍溪叠
2023-03-14
public static <T> Collector<T, ?, T> toSingleton() {
    return Collectors.collectingAndThen(
            Collectors.toList(),
            list -> {
                if (list.size() != 1) {
                    throw new IllegalStateException();
                }
                return list.get(0);
            }
    );
}

我们使用Collectors.CollectingAndThen通过以下方式构造所需的收集器

  1. 使用Collectors.ToList()收集器收集列表中的对象。
  2. 在结尾处应用一个额外的结束器,该结束器返回单个元素-或者如果List.Size!=1则抛出IllegalStateException

用作:

User resultUser = users.stream()
        .filter(user -> user.getId() > 0)
        .collect(toSingleton());

然后,您可以任意自定义此收集器,例如,将异常作为构造函数中的参数,将其调整为允许两个值,等等。

您可以使用包含peek()AtomicInteger的“变通方法”,但实际上您不应该使用它。

您可以做的只是将其收集到列表中,如下所示:

LinkedList<User> users = new LinkedList<>();
users.add(new User(1, "User1"));
users.add(new User(2, "User2"));
users.add(new User(3, "User3"));
List<User> resultUserList = users.stream()
        .filter(user -> user.getId() == 1)
        .collect(Collectors.toList());
if (resultUserList.size() != 1) {
    throw new IllegalStateException();
}
User resultUser = resultUserList.get(0);
 类似资料:
  • 问题内容: 我想将3个列表合并到一个列表中。例如,我有三个列表: 最后我想得到 出,, 有没有更快的方法来合并这三个列表?这是我的代码: 问题答案:

  • 我正在制作一个TicTacToe游戏克隆,需要获得关于玩家想要将其选择放置在哪里的输入。 代码如下:

  • 我使用了将我的数据帧过滤为两列“Worker”和“Time Type”。 示例数据集 我现在只想看到那些“兼职”或“全职”的输出。 到目前为止,我构建的代码是: 但是我得到了错误 有人知道一个简单的方法来解决这个问题吗? 理想情况下,我想以两件事结束: > 显示全职和兼职员工的输出。 另一个显示此参数以外异常的输出,即第2行中的“Tom”显示“paert Tme”,这是一个异常,值得作为单独的输出

  • 0x1是1的十六进制形式。详细信息请参阅此链接。 我正在尝试将转换为。所以我用这个代码。 线程“main”java.lang.NumberFormatException中的异常:对于输入字符串:“0x1” 在java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) 在java.lang.Integer

  • 问题内容: 我知道PHP函数的有害行为 时间 例如,向以下日期添加一个月(+1个月):31.01.2011-> 03.03.2011 我 知道这不是正式的 PHP错误 ,并且该解决方案背后有一些争论,但至少对我而言,这种行为造成了很多时间的浪费(过去和现在),我个人讨厌它。 我发现甚至更陌生的是,例如: MySQL: DATE_ADD(‘2011-01-31’,INTERVAL 1 MONTH)返

  • 我是Hadoop的新手,但这是我上个月的一个学习项目。 为了使这一点足够模糊,以便对其他人有用,让我先抛出基本目标……假设: < li >显然,您有一个大型数据集,包含数百万个基本ASCII文本文件。 < ul > < li >每个文件都是一个“记录” e. g. /user/hduser/data/customer1/YYYY-MM-DD, /user/hduser/data/customer2