Java- stream - Group by Array 4元素并使用Java 8将它们的最后一个元素相加



我有一个字符串数组List<String[]>的列表,看起来像这样:

List<String[]> dataLines = List.of(
new String[]{"2002", "BRBTSS", "BRSTNCNTF212", "BRL", "12670012.4055", "84M", "-101.87", "0"},
new String[]{"2002", "BRBTSS", "BRSTNCNTF212", "BRL", "12670012.4055", "120M", "-102.48", "0"},
new String[]{"2002", "BRBTSS", "BRSTNCNTF212", "BRL", "12670012.4055", "60M", "-103.75", "0"},
new String[]{"2002", "BRBTSS", "BRSTNCNTF212", "BRL", "12670012.4055", "120M", "-10.8", "0"},
new String[]{"2002", "BRBTSS", "BRSTNCNTF212", "BRL", "12670012.4055", "60M", "-110.39", "0"},
new String[]{"2002", "BRBTSS", "BRSTNCNTF212", "BRL", "12670012.4055", "120M", "-10.8", "0"},
new String[]{"2002", "BRBTSS", "BRSTNCNTF212", "CZK", "12670012.4055", "60M", "-103.75", "0"},
new String[]{"2002", "BRBTSS", "BRSTNCNTF212", "BRL", "12670012.4066", "20M", "-10.8", "0"}
);

我想通过分组数组来创建一个新的数组List<String[]>newDataLine,其中0th,1st,3rd5th元素相同,并将它们的6th元素相加。

预期输出:

["2002","BRBTSS","BRSTNCNTF212","BRL","12670012.4055","84M","-101.87","0"],
["2002","BRBTSS","BRSTNCNTF212","BRL","12670012.4055","120M","-124.08000000000001","0"],
["2002","BRBTSS","BRSTNCNTF212","BRL","12670012.4055","60M","-214.14","0"],
["2002","BRBTSS","BRSTNCNTF212","CZK","12670012.4055","60M","-103.75","0"], 
["2002","BRBTSS","BRSTNCNTF212","BRL","12670012.4066","20M","-10.8","0"]

我试过以下方法:

Map<String, Map<String, Map<String, Map<String, Double>>>> map = 
dataLines.stream()
.collect(Collectors.groupingBy(
s -> s[0],
Collectors.groupingBy(s -> s[1],
Collectors.groupingBy(s -> s[3],
Collectors.groupingBy(s -> s[5],
Collectors.summingDouble(s -> Double.valueOf(s[6])))))
));

输出如下:

{2002={BRBTSS={BRL={84M=-101.87, 60M=-214.14, 120M=-124.08000000000001}}}}

如何以上述方式对数据进行分组?

我想要新的列表list <String[]>newDataLine,如果第0,第1,第3,第5是相同的,则添加第6个元素

要以所需的方式对这些数组进行分组并合并它们的数据,可以使用HashMap,非嵌套的。嵌套映射,就像你代码中的那样,很麻烦,很难处理。

为此,我们需要一个对象作为。我将使用Java 16record,但它也可以实现class
public record Key(String s0, String s1, String s2, String s3, String s4, String s5, String s7) {
public Key(String[] line) {
this(line[0], line[1], line[2], line[3], line[4], line[5], line[7]);
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Key key = (Key) o;
return Objects.equals(s0, key.s0) && Objects.equals(s1, key.s1) && Objects.equals(s3, key.s3) && Objects.equals(s5, key.s5);
}

@Override
public int hashCode() {
return Objects.hash(s0, s1, s3, s5);
}

public String[] toArray(Double s6) {
return new String[]{s0, s1, s2, s3, s4, s5, String.valueOf(s6), s7};
}
}

如果我们把它翻译成class,这是它的样子:

public class Key {
private final String s0;
private final String s1;
private final String s2;
private final String s3;
private final String s4;
private final String s5;
private final String s7;

public Key(String s0, String s1, String s2, String s3, String s4, String s5, String s7) {
this.s0 = s0;
this.s1 = s1;
this.s2 = s2;
this.s3 = s3;
this.s4 = s4;
this.s5 = s5;
this.s7 = s7;
}

public Key(String[] line) {
this(line[0], line[1], line[2], line[3], line[4], line[5], line[7]);
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Key key = (Key) o;
return Objects.equals(s0, key.s0) && Objects.equals(s1, key.s1) && Objects.equals(s3, key.s3) && Objects.equals(s5, key.s5);
}

@Override
public int hashCode() {
return Objects.hash(s0, s1, s3, s5);
}

public String[] toArray(Double s6) {
return new String[]{s0, s1, s2, s3, s4, s5, String.valueOf(s6), s7};
}
}

注意:

  • List<String[]>-不是最方便拨号的类型,最好避免将数组和集合混合使用。

  • 这些数组应该是自定义对象首先,因为你希望它们包含特定数量的元素,每个元素都有特定的形状。如果您将它们组织到一个类中,您的数据将具有一个结构,每个元素将成为具有适当数据类型的属性,而不是一个无名的String。

  • 当不想失去精度(例如)时,非常建议使用BigDecimal而不是Double进行浮点计算。虽然summingDouble()是为了减少不准确性而实现的,但double不是计算价格、税率等的好选择。

流应该是这样的:

List<String[]> dataLines = List.of(
new String[]{"2002", "BRBTSS", "BRSTNCNTF212", "BRL", "12670012.4055", "84M", "-101.87", "0"},
new String[]{"2002", "BRBTSS", "BRSTNCNTF212", "BRL", "12670012.4055", "120M", "-102.48", "0"},
new String[]{"2002", "BRBTSS", "BRSTNCNTF212", "BRL", "12670012.4055", "60M", "-103.75", "0"},
new String[]{"2002", "BRBTSS", "BRSTNCNTF212", "BRL", "12670012.4055", "120M", "-10.8", "0"},
new String[]{"2002", "BRBTSS", "BRSTNCNTF212", "BRL", "12670012.4055", "60M", "-110.39", "0"},
new String[]{"2002", "BRBTSS", "BRSTNCNTF212", "BRL", "12670012.4055", "120M", "-10.8", "0"},
new String[]{"2002", "BRBTSS", "BRSTNCNTF212", "CZK", "12670012.4055", "60M", "-103.75", "0"},
new String[]{"2002", "BRBTSS", "BRSTNCNTF212", "BRL", "12670012.4066", "20M", "-10.8", "0"}
);

List<String[]> amountByKey = dataLines.stream()
.collect(Collectors.groupingBy(
Key::new,
Collectors.summingDouble(s -> Double.parseDouble(s[6]))
))
.entrySet().stream()
.map(entry -> entry.getKey().toArray(entry.getValue()))
.collect(Collectors.toList());
newDataLine.forEach(arr -> System.out.println(Arrays.toString(arr)));

输出:

[2002, BRBTSS, BRSTNCNTF212, BRL, 12670012.4055, 84M, -101.87, 0]
[2002, BRBTSS, BRSTNCNTF212, BRL, 12670012.4055, 60M, -214.14, 0]
[2002, BRBTSS, BRSTNCNTF212, BRL, 12670012.4055, 120M, -124.08000000000001, 0]
[2002, BRBTSS, BRSTNCNTF212, BRL, 12670012.4066, 20M, -10.8, 0]
[2002, BRBTSS, BRSTNCNTF212, CZK, 12670012.4055, 60M, -103.75, 0]

相关内容

  • 没有找到相关文章