【问题标题】:Java - Find first and last 2 distinct value [closed]Java - 查找第一个和最后两个不同的值
【发布时间】:2019-03-11 09:42:42
【问题描述】:

我有一个包含如下值的列表,

List<Integer> data = Arrays.asList(10,10,10,9,9,9,9,8,8,8,8,8,8,7,7,7,7,7,7,7,7,7,6,6,6,6);

从那里我需要找到 first(10,9) 和 last(6,7) 不同值的总和和计数。

预期的操作:

First : Count=7, Sum=66
Last :  Count=13, Sum=87

如何使用 java 8 实现这一点?

我试过的代码:

List<Integer> data = Arrays.asList(10,10,10,9,9,9,9,8,8,8,8,8,8,7,7,7,7,7,7,7,7,7,6,6,6,6);
List<Integer> first = data.stream().distinct().collect(Collectors.toList()); //here I am trying get first distinct values(10,10,10,9,9,9,9)
List<Integer> last = data.stream().distinct().collect(Collectors.toList());//here I am trying get last distinct values(7,7,7,7,7,7,7,7,7,6,6,6,6)
int firstSum = first.stream().mapToInt(Integer::intValue).sum();
long firstCount = first.stream().mapToInt(Integer::intValue).count();
int lastSum = last.stream().mapToInt(Integer::intValue).sum();
long lastCount = last.stream().mapToInt(Integer::intValue).count();
System.out.println("First Sum:"+firstSum+" Count"+firstCount);
System.out.println("Last Sum:"+lastSum+" Count"+lastCount);

【问题讨论】:

  • 如何使用 java 8 实现这一点 通过编写一些代码......但无论哪种方式,在这里都很难为您提供帮助,因为这非常不清楚
  • 您标记了您的问题 java-stream,但流不太适合您的要求。我可能会使用老式循环。

标签: java list java-8 java-stream


【解决方案1】:

您可以使用 StreamLinkedHashMap 按值和计数对数字进行分组。

List<Integer> data = Arrays.asList(10, 10, 10, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6);

Map<Integer, Long> map = data.stream().collect(Collectors.groupingBy(Function.identity(), LinkedHashMap::new, Collectors.counting()));
List<Integer> keys = new ArrayList<>(map.keySet());

int a1 = keys.get(0);
int a2 = keys.get(1);
int b1 = keys.get(keys.size() - 1);
int b2 = keys.get(keys.size() - 2);

System.out.format("First : Count=%d, Sum=%d\n", map.get(a1) + map.get(a2), a1 * map.get(a1) + a2 * map.get(a2));
System.out.format("Last : Count=%d, Sum=%d\n", map.get(b1) + map.get(b2), b1 * map.get(b1) + b2 * map.get(b2));

【讨论】:

  • 但是 Arrays.asList(10,10,10,9,9,9,9,8,8,9,9,9,8,8,8,8,7 的 OP 是错误的,7,7,7,7,7,7,7,7,6,6,6,6);这里我们需要从 8,9,9,9,8 中省略 9,因为它不是第一个不同的 9。
  • 只有在列表排序后才能正常工作,如问题所示。除此之外,它经过深思熟虑。
  • 对于未排序的列表,请改用“TreeMap”
  • 错了,@oleg.cherednik。这不会像 MMMMS 要求的那样省略 9。
【解决方案2】:

使用循环。

首先在循环中找到不等于列表中第一个元素的第一个元素。如果没有找到,发出消息并停止。然后在循环中找到不等于这两个元素中的任何一个的第一个元素的索引,或者列表的末尾。现在您知道前两个不同值需要覆盖的范围有多大。现在您可以使用流和limit 进行计数和求和,或者再循环一次。

对最后两个不同的值执行类似的操作,仅从列表的远端循环。

如果列表没有很好的随机访问,请使用ListIterator

流不适合您的任务。至少在涉及未排序列表时不会,例如您对另一个答案的评论。流适用于每个元素的处理不依赖于之前或之后的元素的情况。在您的任务中,计数和总和中可能包含或省略 9,具体取决于列表中是否出现 8。

编辑:学术练习流

我承认这对我来说是一个挑战。这是一个使用流的解决方案。我不推荐它,我坚持我上面所说的。它甚至可以用来显示流解决方案的复杂程度。

    List<Integer> data = Arrays.asList(10, 10, 10, 9, 9, 9, 9, 8, 8, 9, 9, 9,
            8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6);
    if (data.isEmpty()) {
        System.out.println("No elements");
    } else {
        int firstDistinct = data.get(0);
        OptionalInt secondDistinctOpt = data.stream()
                .mapToInt(Integer::intValue)
                .dropWhile(i -> i == firstDistinct)
                .findFirst();
        assert secondDistinctOpt.stream().noneMatch(sd -> sd == firstDistinct);
        Optional<IntSummaryStatistics> statsOpt = secondDistinctOpt.stream()
                .mapToObj(secondDistinct -> data.stream()
                                .mapToInt(Integer::intValue)
                                .takeWhile(i -> i == firstDistinct || i == secondDistinct)
                                .summaryStatistics())
                .findAny();
        statsOpt.ifPresentOrElse(
                stats -> System.out.println("Count = " + stats.getCount() + " Sum = "+ stats.getSum()),
                () -> System.out.println("No 2 distinct values"));
    }

计数 = 7 总和 = 66

对于最后两个不同的值,您可以使用 Collections.reverse 反转列表并重复。

进一步编辑:我故意从your comment 中获取您的示例列表,而不是您问题中的列表,以证明前 8 之后的 9 不包括在总和和计数中。

【讨论】:

  • 问题的输入不匹配,尽管输出保持不变:)
猜你喜欢
  • 2019-08-12
  • 2012-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-28
  • 1970-01-01
  • 2023-03-09
  • 2019-12-09
相关资源
最近更新 更多