寻找第一个免费"索引"使用java流

时间:2016-12-20 22:13:09

标签: 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())
{
    // 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.
}

我要求别人帮我找到合适的语法或提出更好的解决方案。

3 个答案:

答案 0 :(得分:7)

最有效的方法是收集到BitSet

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,如果根本没有匹配元素,则下一个空格将为零。

答案 1 :(得分:4)

你可以:

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

    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());
    

答案 2 :(得分:0)

为了好玩,如果您知道,您最多有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;
    }

这就是@Holger所做的(来自我的+1),但没有使用BitSet的额外惩罚。