“寻找第一个自由”;索引“;使用java流

“寻找第一个自由”;索引“;使用java流,java,java-8,java-stream,Java,Java 8,Java Stream,我需要在我的文件系统中找到第一个以名称流为源的自由索引 考虑列表:[“New2”、“New4”、“New0”、“New1”、…] 第一个未使用的索引为3 int index = 0; try (IntStream indexes = names.stream() .filter(name -> name.startsWith("New")) .mapToInt(Integer::parseInt) .distinct() .sorted()) { /

我需要在我的文件系统中找到第一个以名称流为源的自由索引

考虑列表:[“New2”、“New4”、“New0”、“New1”、…] 第一个未使用的索引为3

int index = 0;
try (IntStream indexes = names.stream()
    .filter(name -> name.startsWith("New"))
    .mapToInt(Integer::parseInt)
    .distinct()
    .sorted())
{
    // I was thinking about making possible indexes stream, removing existig ones from try-with-resource block, and getting .min().
    IntStream.rangeClosed(0, 10)... // Idk what to do.
}
我请求某人帮助我找到适合我想法的语法或提出更好的解决方案。

您可以:

  • 从每个名称中提取数字部分
  • 将使用过的索引存储在一个集合中
  • 在从0到列表大小的范围内迭代
  • 不在已用集合中的第一个索引可用
  • 例如:

    List<String> names = Arrays.asList("New2", "New4", "New0", "New1");
    Set<Integer> taken = names.stream()
        .map(s -> s.replaceAll("\\D+", ""))
        .map(Integer::parseInt)
        .collect(Collectors.toSet());
    int first = IntStream.range(0, names.size())
        .filter(index -> !taken.contains(index))
        .findFirst()
        .orElse(names.size());
    
    List name=Arrays.asList(“New2”、“New4”、“New0”、“New1”);
    Set take=names.stream()
    .map(s->s.replaceAll(\\D+,“”)
    .map(整数::parseInt)
    .collect(收集器.toSet());
    int first=IntStream.range(0,names.size())
    .filter(索引->!take.contains(索引))
    .findFirst()
    .orElse(names.size());
    
    最有效的方法是收集到
    位集中

    int first = names.stream()
        .filter(name -> name.startsWith("New"))
        .mapToInt(s -> Integer.parseInt(s.substring(3)))
        .collect(BitSet::new, BitSet::set, BitSet::or).nextClearBit(0);
    
    请注意,这些位本质上是经过排序和区分的。此外,总会有一个“免费”索引。如果
    0
    和最大值之间没有差距,下一个自由值将是最大值+1,如果根本没有匹配元素,下一个自由值将是零。

    有趣的是,如果你知道你最多有63个条目

        private static int firstMissing(List<Long> input) {
            if (!input.contains(0L)) {
               return 0;
            }
    
            long firstMissing = Long.lowestOneBit(~input.stream().reduce(1L, (i, j) -> i | 1L << j));
    
            int result = 0;
            while (firstMissing != 0) {
               ++result;
               firstMissing = firstMissing >> 1;
            }
    
            return result - 1;
        }
    
    private static int firstMissing(列表输入){
    如果(!input.contains(0L)){
    返回0;
    }
    long firstMissing=long.lowstonebit(~input.stream().reduce(1L,(i,j)->i | 1L>1;
    }
    返回结果-1;
    }
    

    这就是@Holger所做的(+1),但是没有使用位集的额外惩罚。

    Integer::parseInt
    将失败,除非您首先删除前缀。为什么不使用
    collect(toSet())
    ?或者,您可以收集到一个列表,并将索引与值进行比较(
    .filter(i->take.get(i)>i)
    )。谢谢@shmosel,收集到一套更好,更新。那确实很酷!+1(复选标记应该归你)我喜欢一行!谢谢!