我有一个列表包含以下值,
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)不同值的总和和计数。
期望的OP:
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);
答案 0 :(得分:2)
您可以按数值对数字进行分组,并使用Stream
到LinkedHashMap
进行计数。
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));
答案 1 :(得分:1)
使用循环。
首先在循环中找到与列表中的第一个元素不相等的第一个元素。如果未找到,则发出消息并停止。然后在循环中找到第一个元素的索引,该索引不等于这两个元素中的任何一个或列表的末尾。现在您知道前两个不同值需要覆盖的范围。现在,您可以使用流和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个计数。