使用Java lambda表达式从映射中获取特定条目及其索引

使用Java lambda表达式从映射中获取特定条目及其索引,java,lambda,hashmap,java-8,java-stream,Java,Lambda,Hashmap,Java 8,Java Stream,我有一张地图,上面有以下条目: {‘John’:false, 'Mike':false, 'Tom':true, 'Harry':false, 'Bob': false} 我需要找到第一个条目及其值为true的索引。 这里我应该得到Tom和3(比如,索引以1开头) 我可以迭代贴图并获得以下值: int itr=0; for(Iterator<Map.Entry<String, Boolean>> entries = map.entrySet().iterator

我有一张
地图
,上面有以下条目:

{‘John’:false,
 'Mike':false,
 'Tom':true,
 'Harry':false,
 'Bob': false}
我需要找到第一个条目及其值为true的索引。 这里我应该得到Tom和3(比如,索引以1开头)

我可以迭代贴图并获得以下值:

int itr=0;
for(Iterator<Map.Entry<String, Boolean>> entries = map.entrySet().iterator; entries.hasNext(); ) {
    itr++;
    Map.Entry<String, Boolean> entry = entries.next();
    if(entry.getValue()) {
       name = entry.getKey();
       index = itr;
    }
}
intitr=0;
for(Iterator entries=map.entrySet().Iterator;entries.hasNext();){
itr++;
Map.Entry=entries.next();
if(entry.getValue()){
name=entry.getKey();
指数=itr;
}
}

但是,我也在研究lambda表达式。

如果您可以保证映射实际上是LinkedHashMap(这样它就保留了插入顺序),那么您可以执行以下操作:

List<Map.Entry<String, Boolean>> l = map.entrySet().stream().collect(Collectors.toList());
    IntStream.range(0, l.size())
            .mapToObj(i -> new AbstractMap.SimpleEntry<>(i, l.get(i)))
            .filter(e -> e.getValue().getValue())
            .map(e -> new AbstractMap.SimpleEntry<>(e.getValue().getKey(), e.getKey()))
            .findFirst();
AtomicInteger idx = new AtomicInteger();

String name = map.entrySet().stream()
   .peek(e -> idx.incrementAndGet())
   .filter(Map.Entry::getValue)
   .map(Map.Entry::getKey)
   .findFirst().orElse(null);
int itr = idx.get();
List l=map.entrySet().stream().collect(Collectors.toList());
IntStream.range(0,l.size())
.mapToObj(i->newAbstractMap.SimpleEntry(i,l.get(i)))
.filter(e->e.getValue().getValue())
.map(e->new AbstractMap.SimpleEntry(e.getValue().getKey(),e.getKey())
.findFirst();

如果您可以保证映射实际上是一个LinkedHashMap(这样它就保留了插入顺序),那么您可以这样做:

List<Map.Entry<String, Boolean>> l = map.entrySet().stream().collect(Collectors.toList());
    IntStream.range(0, l.size())
            .mapToObj(i -> new AbstractMap.SimpleEntry<>(i, l.get(i)))
            .filter(e -> e.getValue().getValue())
            .map(e -> new AbstractMap.SimpleEntry<>(e.getValue().getKey(), e.getKey()))
            .findFirst();
AtomicInteger idx = new AtomicInteger();

String name = map.entrySet().stream()
   .peek(e -> idx.incrementAndGet())
   .filter(Map.Entry::getValue)
   .map(Map.Entry::getKey)
   .findFirst().orElse(null);
int itr = idx.get();
List l=map.entrySet().stream().collect(Collectors.toList());
IntStream.range(0,l.size())
.mapToObj(i->newAbstractMap.SimpleEntry(i,l.get(i)))
.filter(e->e.getValue().getValue())
.map(e->new AbstractMap.SimpleEntry(e.getValue().getKey(),e.getKey())
.findFirst();

我认为不可能满足以下所有条件:

  • 解决方案应该是惰性的(找到答案后停止迭代映射)
  • 解决方案不应显式使用迭代器()或拆分器()
  • 解决方案应符合流API规范(尤其是中间lambda不应有副作用)
  • 解决方案不应使用第三方流扩展
  • 如果您同意违反#1,请检查@Eugene的答案。如果您同意违反#2,那么问题中的代码很好。如果你同意违反#3,你可以这样做:

    List<Map.Entry<String, Boolean>> l = map.entrySet().stream().collect(Collectors.toList());
        IntStream.range(0, l.size())
                .mapToObj(i -> new AbstractMap.SimpleEntry<>(i, l.get(i)))
                .filter(e -> e.getValue().getValue())
                .map(e -> new AbstractMap.SimpleEntry<>(e.getValue().getKey(), e.getKey()))
                .findFirst();
    
    AtomicInteger idx = new AtomicInteger();
    
    String name = map.entrySet().stream()
       .peek(e -> idx.incrementAndGet())
       .filter(Map.Entry::getValue)
       .map(Map.Entry::getKey)
       .findFirst().orElse(null);
    int itr = idx.get();
    

    如果你违反了第4条,你可以考虑使用我的免费库:

    Map.Entry=streamx.of(Map.entrySet())/(名称,bool)
    .zipWith(IntStreamEx.ints().boxed())/((名称,bool),索引)
    .filterKeys(Map.Entry::getValue)//按bool筛选
    .mapKeys(Map.Entry::getKey)/(名称、索引)
    .findFirst()
    .orElse(空);
    if(条目!=null){
    字符串名称=entry.getKey();
    int itr=entry.getValue();
    }
    
    我认为不可能满足以下所有条件:

  • 解决方案应该是惰性的(找到答案后停止迭代映射)
  • 解决方案不应显式使用迭代器()或拆分器()
  • 解决方案应符合流API规范(尤其是中间lambda不应有副作用)
  • 解决方案不应使用第三方流扩展
  • 如果您同意违反#1,请检查@Eugene的答案。如果您同意违反#2,那么问题中的代码很好。如果你同意违反#3,你可以这样做:

    List<Map.Entry<String, Boolean>> l = map.entrySet().stream().collect(Collectors.toList());
        IntStream.range(0, l.size())
                .mapToObj(i -> new AbstractMap.SimpleEntry<>(i, l.get(i)))
                .filter(e -> e.getValue().getValue())
                .map(e -> new AbstractMap.SimpleEntry<>(e.getValue().getKey(), e.getKey()))
                .findFirst();
    
    AtomicInteger idx = new AtomicInteger();
    
    String name = map.entrySet().stream()
       .peek(e -> idx.incrementAndGet())
       .filter(Map.Entry::getValue)
       .map(Map.Entry::getKey)
       .findFirst().orElse(null);
    int itr = idx.get();
    

    如果你违反了第4条,你可以考虑使用我的免费库:

    Map.Entry=streamx.of(Map.entrySet())/(名称,bool)
    .zipWith(IntStreamEx.ints().boxed())/((名称,bool),索引)
    .filterKeys(Map.Entry::getValue)//按bool筛选
    .mapKeys(Map.Entry::getKey)/(名称、索引)
    .findFirst()
    .orElse(空);
    if(条目!=null){
    字符串名称=entry.getKey();
    int itr=entry.getValue();
    }
    
    HashMap
    不维护其元素的顺序@用户1639485按索引您可能是指在获得价值之前,您看到了多少条目?如果是这样的话,这是不可靠的,因为当地图的某个重新大小发生时,该条目可能会移动。除非你的映射保持了顺序,比如
    LinkedHashMap
    @Eugene,否则我认为你ping错了用户,你基本上说了我说的话。请参见和。你的循环返回最后一次出现,而不是第一次。
    HashMap
    不会保持其元素的顺序@用户1639485按索引您可能是指在获得价值之前,您看到了多少条目?如果是这样的话,这是不可靠的,因为当地图的某个重新大小发生时,该条目可能会移动。除非你的映射保持了顺序,比如
    LinkedHashMap
    @Eugene,否则我认为你ping错了用户,你基本上说了我说的话。请看和。你的循环返回最后一次,而不是第一次。两个选项都很好。一个加号。StreamEx不是有
    takeWhile
    int index=StreamEx.of(map.values()).takeWhile(b->!b.count();字符串名称=map.keySet().stream().skip(index).findFirst().orElse(null)..@Holger,是的,这样的解决方案也是可能的,尽管它是两次通过。顺便说一句,这是一个很好的版本,因为它在Java9中可用。也可以使用streamx
    long idx=streamx.ofValues(map).indexOf(b->b).orElse(-1)
    。其他单通道StreamEx解决方案也可以,如
    EntryStream.of(map).takeWhileInclusive(e->!e.getValue()).keys().zipWith(intstreamx.ints().boxed()).reduce((a,b)->b)
    。这两个选项都非常好。一个加号。StreamEx不是有
    takeWhile
    int index=StreamEx.of(map.values()).takeWhile(b->!b.count();字符串名称=map.keySet().stream().skip(index).findFirst().orElse(null)..@Holger,是的,这样的解决方案也是可能的,尽管它是两次通过。顺便说一句,这是一个很好的版本,因为它在Java9中可用。也可以使用streamx
    long idx=streamx.ofValues(map).indexOf(b->b).orElse(-1)
    。其他单通道StreamEx解决方案也可以,如
    EntryStream.of(map).takeWhileInclusive(e->!e.getValue()).keys().zipWith(intstreamx.ints().boxed()).reduce((a,b)->b)