本文介紹了使用STREAMS實(shí)現(xiàn)Java透視表的處理方法,對大家解決問題具有一定的參考價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧!
問題描述
我已經(jīng)在這個(gè)問題上掙扎了幾天了。我正在嘗試使用Java Streams創(chuàng)建透視功能。我只需要執(zhí)行
總和、計(jì)數(shù)、最大值、最小值和平均值。對于輸入,我得到一個(gè)透視表列索引、一個(gè)透視表行索引數(shù)組和要計(jì)算的值。
問題是數(shù)據(jù)在列表中,其中對象可以是字符串、整數(shù)或雙精度。但我要到運(yùn)行時(shí)才能知道。我必須以List<;List<;Object>的形式返回我的結(jié)果。
我遇到了MAX/MIN問題(我假設(shè)平均值將類似于MAX和MIN)
為了透視多個(gè)表值,我創(chuàng)建了一個(gè)類來使用我的第二個(gè)GroupingBy
這將不會編譯,我不確定要與什么進(jìn)行比較,不確定在哪里將對象轉(zhuǎn)換為int,或者我是否需要這樣做。我想用一個(gè)流來完成這一切,但我不確定這是否可能。我做錯(cuò)了什么,或者我可以用不同的方式來做。提前謝謝。
package pivot.test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
public class PivotTest {
List<List<Object>> rows = new ArrayList<List<Object>>();
public PivotTest() throws Exception {
rows.add(Arrays.asList(new Object[]{ "East", "Boy", "Tee", 10, 12.00}));
rows.add(Arrays.asList(new Object[]{ "East", "Boy", "Golf", 15, 20.00}));
rows.add(Arrays.asList(new Object[]{ "East", "Girl", "Tee", 8, 14.00}));
rows.add(Arrays.asList(new Object[]{ "East", "Girl", "Golf", 20, 24.00}));
rows.add(Arrays.asList(new Object[]{ "West", "Boy", "Tee", 5, 12.00}));
rows.add(Arrays.asList(new Object[]{ "West", "Boy", "Golf", 12, 20.00}));
rows.add(Arrays.asList(new Object[]{ "West", "Girl", "Tee", 15, 14.00}));
rows.add(Arrays.asList(new Object[]{ "West", "Girl", "Golf", 10, 24.00}));
}
// Dynamic Max based upon Column, Value to sum, and an array of pivot rows
public void MaxTable(int colIdx, int valueIdx, int... rowIdx) {
Map<Object, Map<Object, Integer>> myList = newRows.stream().collect(
Collectors.groupingBy(r -> ((List<Object>) r).get(colIdx),
Collectors.groupingBy( r -> new PivotColumns(r, rowIdx),
Collectors.collectingAndThen( Collectors.maxBy(Comparator.comparingInt(???)),
r -> ((List<Object>) r).get(valueIdx)))));
System.out.println("Dynamic MAX PIVOT"); System.out.println(myList);
}
public static void main(String[] args) {
try {
PivotTest p = new PivotTest();
System.out.println("
Streams PIVOT with index values inside a List
");
p.MaxTable(0, 3, new int[] { 2 });
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class PivotColumns {
ArrayList<Object> columns;
public PivotColumns(
List<Object> objs, int... pRows) {
columns = new ArrayList<Object>();
for (int i = 0; i < pRows.length; i++) {
columns.add(objs.get(pRows[i]));
}
}
public void addObject(Object obj) {
columns.add(obj);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((columns == null) ? 0 : columns.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
PivotColumns other = (PivotColumns) obj;
if (columns == null) {
if (other.columns != null)
return false;
} else if (!columns.equals(other.columns))
return false;
return true;
}
public String toString() {
String s = "";
for (Object obj : columns) {
s += obj + ",";
}
return s.substring(0, s.lastIndexOf(','));
}
}
推薦答案
由于已知所有可能的值(String
、Integer
、Double
)都是Comparable
,因此您可以對Comparable
接口執(zhí)行未經(jīng)檢查的強(qiáng)制轉(zhuǎn)換。此外,不要忘記打開可選的包裝。最后,如果我理解正確的話,結(jié)果應(yīng)該是Map<Object, Map<Object, Object>> myList
,而不是Map<Object, Map<Object, Integer>> myList
,因?yàn)槟牧锌赡苡蟹钦麛?shù)值:
public void MaxTable(int colIdx, int valueIdx, int... rowIdx) {
Map<Object, Map<Object, Object>> myList = newRows.stream().collect(
Collectors.groupingBy(r -> r.get(colIdx),
Collectors.groupingBy( r -> new PivotColumns(r, rowIdx),
Collectors.collectingAndThen( Collectors.maxBy(
Comparator.comparing(r -> (Comparable<Object>)(((List<Object>) r).get(valueIdx)))),
r -> r.get().get(valueIdx)))));
System.out.println("Dynamic MAX PIVOT"); System.out.println(myList);
}
結(jié)果:
> p.MaxTable(0, 3, new int[] { 1 });
{West={Girl=15, Boy=12}, East={Girl=20, Boy=15}}
> p.MaxTable(0, 4, new int[] { 1 });
{West={Girl=24.0, Boy=20.0}, East={Girl=24.0, Boy=20.0}}
如您所見,您可以同時(shí)處理Integer
和Double
列。甚至可以處理String
(將按詞典順序選擇最大值)。
對于平均值,您可以假設(shè)列值是數(shù)字(Number
類,Integer
或Double
),并收集到Double
(整數(shù)的平均值也可以是非整數(shù)):
public void AverageTable(int colIdx, int valueIdx, int... rowIdx) {
Map<Object, Map<Object, Double>> myList = newRows.stream().collect(
Collectors.groupingBy(r -> r.get(colIdx), Collectors
.groupingBy(r -> new PivotColumns(r, rowIdx),
Collectors.averagingDouble(r -> ((Number) (r
.get(valueIdx))).doubleValue()))));
System.out.println("Dynamic AVG PIVOT"); System.out.println(myList);
}
輸出:
> p.AverageTable(0, 3, new int[] { 1 });
{West={Girl=12.5, Boy=8.5}, East={Girl=14.0, Boy=12.5}}
> p.AverageTable(0, 4, new int[] { 1 });
{West={Girl=19.0, Boy=16.0}, East={Girl=19.0, Boy=16.0}}
這篇關(guān)于使用STREAMS實(shí)現(xiàn)Java透視表的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,