Java 获取匹配布尔值的第一个元素索引的流方法

Java 获取匹配布尔值的第一个元素索引的流方法,java,java-8,java-stream,Java,Java 8,Java Stream,我有一个列表。我想获得流中具有特定用户名的(第一个)用户的索引。我不希望实际要求用户与所描述的用户具有相同的用户名,即.equals() 我可以想出一些丑陋的方法(迭代和计数),但感觉应该有一种很好的方法来实现这一点,可能是通过使用流。到目前为止,我得到的最好结果是: int index = users.stream() .map(user -> user.getName()) .collect(Collectors.toList()) .indexOf(usern

我有一个
列表
。我想获得流中具有特定用户名的(第一个)用户的索引。我不希望实际要求
用户
与所描述的
用户
具有相同的用户名,即
.equals()

我可以想出一些丑陋的方法(迭代和计数),但感觉应该有一种很好的方法来实现这一点,可能是通过使用流。到目前为止,我得到的最好结果是:

int index = users.stream()
    .map(user -> user.getName())
    .collect(Collectors.toList())
    .indexOf(username);
这不是我写过的最差的代码,但也不是很好。它也没有那么灵活,因为它依赖于有一个映射函数,映射到一个带有
.equals()
函数的类型,该函数描述了您要查找的属性;我更希望有一些可以用于任意
函数的东西


有人知道怎么做吗?

有时候java中没有pythonic
zipWithIndex
。所以我遇到了这样的事情:

optionant indexOpt=IntStream.range(0,users.size())
.filter(i->searchName.equals(users.get(i)))
.findFirst();
或者,您可以使用库中的
zipWithIndex

注意

如果users.get不是固定时间操作,则该解决方案可能会非常耗时。

请尝试以下操作:

IntStream.range(0, users.size())
    .filter(userInd-> users.get(userInd).getName().equals(username))
    .findFirst()
    .getAsInt();
你可以试试我做的图书馆。那个图书馆有一个方便的索引方法

这是一个简单的例子:

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);
List users=asList(新用户(“Vas”)、新用户(“Innokenty”)、新用户(“WAT”);
长索引=流x.of(用户)
.indexOf(user->user.name.equals(“Innokenty”))
.getAsLong();
系统输出打印项次(索引);

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

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;

当谓词为false时,peek增量索引i因此当谓词为true时,i比匹配的谓词=>
i.get()-1
使用Guava库:
int index=

Iterables.indexOf(users,u->searchName.equals(u.getName())
库中有
detectIndex
方法,它采用
谓词

int index = ListIterate.detectIndex(users, user -> username.equals(user.getName()));
如果在
User
类上有一个方法,该方法返回
boolean
如果
username
匹配,则可以使用以下方法:

int index = ListIterate.detectIndexWith(users, User::named, username);

注意:我是Eclipse Collections的提交人,它为我提供了用户信息,但不是您的索引级别,您能在这里帮助我提供处理该用例的建议吗?与其他操作索引一样,使用
orElse(-1)
,而不是
get()
。但是代码将在这里崩溃。user.get(userInd)。如果返回的用户为null,则返回getName()。stream API是否也处理NullPointerexception?@AmanSinghal IMO,列表中不应该有空值,但空列表或缺少请求名称的列表才有意义。如果你得到一个NPE是因为有人在列表中输入了一个空值,那就是他们的错误。我也可以跳过这一对,只需在筛选操作中查找具有给定索引的用户。。。不确定这是好是坏。@EdwardPeters肯定是好。至少这消除了额外的内存traffic@vsminkov,你在这里要小心。没有人说这个名单有O(1)个访问权限。@SerCe很公平。另一个选项是像protonpack一样实现自定义拆分器。我要记下为什么“迭代”很难看?流和索引不能很好地混合。在这一点上,你通常最好还是回到旧式的循环中去。@Andreas我喜欢streams的一点是将与集合相关的逻辑与被请求的特定事物分离开来。在这种情况下,可能会提出大量不同的问题,这些问题只与核心
函数不同,因此感觉应该有一种方法来处理这些问题,将其从常规集合逻辑中抽象出来。@Andreas因为您在这里手动描述所有与结构相关的代码,而不是将其划分。至于另一个问题,我只是忘记了
谓词
是一件事。整洁的Java 11解决方案:
int index=users.stream().map(User::getName).takeWhile(not(username::equals)).count()最具可读性的解决方案和机会番石榴-就像commons lang-已经在您的POM中;)比IntStream IMHO更优雅!