Java 如何在不排序数组的情况下计算数组中的整数组?

Java 如何在不排序数组的情况下计算数组中的整数组?,java,arrays,java-stream,counting,Java,Arrays,Java Stream,Counting,我的目标是能够对数组中相同整数的组进行计数。例如,在这样的数组中,{1,1,1,2,2,3,1,1},有4个组: 大小至少为1:3组 大小至少为2:1组 尺寸至少为3号 在不排序数组的情况下完成此操作时遇到问题。当它被排序时,我会记不清数组末尾的两组1,因为它被放在其他1组的旁边 int result = (int) Stream.of(1, 1, 1, 2, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 5, 4, 4, 4, 6)

我的目标是能够对数组中相同整数的组进行计数。例如,在这样的数组中,
{1,1,1,2,2,3,1,1}
,有4个组:

  • 大小至少为1:3组
  • 大小至少为2:1组
  • 尺寸至少为3号
在不排序数组的情况下完成此操作时遇到问题。当它被排序时,我会记不清数组末尾的两组1,因为它被放在其他1组的旁边

int result = (int) Stream.of(1, 1, 1, 2, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 5, 4, 4, 4, 6)
        .collect(Collectors.groupingBy(i -> i))
        .entrySet().stream()
        .filter(entry -> entry.getValue().size() >= 1) // specify the size
        .count()

return result;
每种尺寸的预期输出如下所示:

size 1 count == 8

size 2 count == 5

size 6 count == 1

size 8 count == 1
size 1 count == 6

size 2 count == 3

size 6 count == 2

size 8 count == 1
实际输出如下:

size 1 count == 8

size 2 count == 5

size 6 count == 1

size 8 count == 1
size 1 count == 6

size 2 count == 3

size 6 count == 2

size 8 count == 1
差异是在计数之前对数组进行排序的结果。有没有办法做到这一点

编辑: 组本质上是相同整数重复的任何位置,直到前面有一个不同值的整数;因此,在这段代码中,大小为2的组是索引0到2(包括)、索引4到5(包括)、索引6到15(包括)、索引16到18(包括)和索引20到22(包括)处的任意组。由于有5个组的大小至少为2,因此应返回计数5

为我的目标而编写的命令式代码

Scanner key = new Scanner("1 1 1 2 1 1 3 3 3 3 3 3 3 3 3 3 4 4 4 5 4 4 4 6");

        int cnt = 0;
        int counter = 0;
        int i = 0;

            while(key.hasNextInt()) {   
                int next = key.nextInt();

                if(next == array[i]) {
                    counter++;
                }

                if(i + 1 < array.length && i -1 >= 0 
                   && counter >=size  
                   && next != array[i + 1] 
                   && next == array[i-size + 1]) {
                    cnt++;
                    counter = 0;
                }
                i++;
            }
        return cnt;
这个循环的问题是我认为它跳过了数组的第一个片段和最后一个片段

我没有与方式相同的排序问题

理想情况下,这不需要任何外部实用程序/库

,如果使用是一个选项,那么它会变得非常容易

IntStream s = IntStream.of(1, 1, 1, 2, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 5, 4, 4, 4, 6);
List<List<Integer>> t = IntStreamEx.of (s).boxed().groupRuns(Integer::equals).toList();
t.forEach(e -> {
  System.out.println(String.format("Group of %s - %s times", e.get(0), e.size()));
});
intstreams=IntStream.of(1,1,1,2,1,1,3,3,3,3,3,3,3,3,4,4,5,4,4,6);
List t=intstreamx.of(s).boxed().groupRuns(Integer::equals).toList();
t、 forEach(e->{
System.out.println(String.format(“一组%s-%s次”,e.get(0),e.size());
});

首先,我建议查找所有子组。为此,您可以使用自定义收集器使用
Stream.collect()

List<List<Integer>> sublists = IntStream.of(1, 1, 1, 2, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 5, 4, 4, 4, 6)
        .collect(ArrayList::new, (lists, value) -> {
            if (lists.isEmpty() || lists.get(lists.size() - 1).stream().noneMatch(e -> e == value)) {
                lists.add(new ArrayList<>());
            }
            lists.get(lists.size() - 1).add(value);
        }, (l1, l2) -> {
            throw new RuntimeException("not supported for parallel streams");
        });
现在,您可以使用它对列表大小进行分组:

Map<Integer, Long> result = sublists.stream()
        .collect(Collectors.groupingBy(List::size, Collectors.counting()));
result.forEach((size, count) -> System.out.println(String.format("size %s count %s", size, count)));
要以最小长度计算所有组,可以使用:

Map<Integer, Long> result = IntStream.rangeClosed(1, sublists.stream().mapToInt(List::size).max().orElse(0)).boxed()
        .collect(Collectors.toMap(Function.identity(), i -> sublists.stream().filter(l -> l.size() >= i).count()));
result.forEach((size, count) -> System.out.println(String.format("size %s count %s", size, count)));
要仅获取一组预定义的大小(例如,
1、2、6、8
),您可以修改上一个解决方案:

Map<Integer, Long> result = IntStream.of(1, 2, 6, 8).boxed()
        .collect(Collectors.toMap(Function.identity(), i -> sublists.stream().filter(l -> l.size() >= i).count()));
result.forEach((size, count) -> System.out.println(String.format("size %s count %s", size, count)));

首先,我要说的是,这并不是
API的真正目的,但是,这是可能的,也许不是最优雅的方式,但仍然是可能的

这里有一个可能的解决方案供您使用

  • 将所有内容转换为一个大字符串,并在数字不同的地方拆分
  • 现在,通过流收集组及其计数
  • 将较高组的数量添加到每个较小组中(以获得至少一个
    逻辑)
  • 在那里,你应该有你需要的所有信息
  • 演示
    您能否解释一下,如何根据提供的输入来定义
    大小1计数==8
    size 1 count 8
    size 2 count 5
    size 3 count 4
    size 4 count 1
    size 5 count 1
    size 6 count 1
    size 7 count 1
    size 8 count 1
    size 9 count 1
    size 10 count 1
    
    Map<Integer, Long> result = IntStream.of(1, 2, 6, 8).boxed()
            .collect(Collectors.toMap(Function.identity(), i -> sublists.stream().filter(l -> l.size() >= i).count()));
    result.forEach((size, count) -> System.out.println(String.format("size %s count %s", size, count)));
    
    size 1 count 8
    size 2 count 5
    size 6 count 1
    size 8 count 1
    
    String[] groups = Stream.of(1, 1, 1, 2, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 5, 4, 4, 4, 6)
            .map(String::valueOf)
            .collect(Collectors.joining(","))
            .split("(?<=(\\d))(,)(?!\\1)");
    
    Map<Integer, Long> groupedByGroupSizes = Arrays.stream(groups)
            .map(group -> group.split(",").length)
            .collect(Collectors.groupingBy(x -> x, Collectors.counting()));
    
    TreeMap<Integer, Long> integerLongTreeMap = new TreeMap<>(groupedByGroupSizes);
    int size = integerLongTreeMap.size();
    
    for (Integer integer : integerLongTreeMap.keySet()) {
        Long value = integerLongTreeMap.get(integer);
        integerLongTreeMap.put(integer, value + --size);
    }
    
    integerLongTreeMap.entrySet().forEach(entry -> System.out.println(String.format("of at least size %s: %s groups", entry.getKey(), entry.getValue())));
    
    of at least size 1: 6 groups
    of at least size 2: 3 groups
    of at least size 3: 4 groups
    of at least size 10: 1 groups