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更优雅!