Stream Way获取匹配boolean的第一个元素的索引

Edw*_*ers 40 java java-8 java-stream

我有一个List<Users>.我想用特定的用户名获取流中(第一个)用户的索引.我不想竟要求User.equals()一些描述User,只是为了有相同的用户名.

我可以想到这样做的丑陋方法(迭代和计数),但感觉应该有一个很好的方法来做到这一点,可能是通过使用Streams.到目前为止,我所拥有的最好的是:

int index = users.stream()
    .map(user -> user.getName())
    .collect(Collectors.toList())
    .indexOf(username);
Run Code Online (Sandbox Code Playgroud)

这不是我写过的最糟糕的代码,但它并不好.它也不是那么灵活,因为它依赖于一个带有.equals()描述你正在寻找的属性的函数的类型的映射函数; 我宁愿有一些可以随心所欲的东西Function<T, Boolean>

谁知道怎么样?

vsm*_*kov 53

偶尔zipWithIndex在java中没有pythonic .所以我遇到了类似的东西:

OptionalInt indexOpt = IntStream.range(0, users.size())
     .filter(i -> searchName.equals(users.get(i)))
     .findFirst();
Run Code Online (Sandbox Code Playgroud)

或者您可以使用zipWithIndexprotonpack

注意

如果users.get不是恒定时间操作,那么该解决方案可能是耗时的.

  • @vsminkov,你在这应该小心.没有人说该列表有O(1)访问权限. (2认同)
  • @SerCe足够公平.另一种选择是像protonpack那样实现自定义分裂器.我会写一张便条 (2认同)

Ama*_*hal 11

试试这个:

IntStream.range(0, users.size())
    .filter(userInd-> users.get(userInd).getName().equals(username))
    .findFirst()
    .get();
Run Code Online (Sandbox Code Playgroud)

  • 希望找到用户,否则代码崩溃. (13认同)
  • 而不是`get()`,使用`orElse(-1)`,就像其他操作索引一样. (7认同)
  • @AmanSinghal IMO,列表中不应该有空值,但空列表或缺少请求名称的列表是有意义的。如果你因为有人将空值放入列表而得到 NPE,那是他们的错 (2认同)

kar*_*aze 10

使用番石榴库: int index = Iterables.indexOf(users, u -> searchName.equals(u.getName()))

  • 最易读的解决方案和机会 guava - 就像 commons-lang - 已经在你的 POM 中;)比 IntStream 恕我直言更优雅! (2认同)

Ser*_*rCe 7

您可以尝试StreamEx所作库Tagir Valeev.该库有一个方便的#indexOf方法.

这是一个简单的例子:

List<User> users = asList(new User("Vas"), new User("Innokenty"), new User("WAT"));
long index = StreamEx.of(users)
        .indexOf(user -> user.name.equals("Innokenty"))
        .getAsLong();
System.out.println(index);
Run Code Online (Sandbox Code Playgroud)


hib*_*our 5

没有任何外部库的解决方案

AtomicInteger i = new AtomicInteger(); // any mutable integer wrapper
int index = users.stream()
    .peek(v -> i.incrementAndGet())
    .anyMatch(user -> user.getName().equals(username)) ? // your predicate
    i.get() - 1 : -1;
Run Code Online (Sandbox Code Playgroud)

在谓词为假时查看增量索引 i 因此当谓词为真时,我比匹配的谓词多 1 => i.get() -1