簡體   English   中英

Java 8流如何將第2列映射到地圖

[英]java 8 stream how to map 2 column into the map

我有一張桌子:

名稱| 數據 NUM
item1 | 16 | 2
item2 | 17 | 3
item1 | 16 |

我想將其轉換為:

{item1:{16 + 16,2 + 5},item2:{17,3}}

但是,我只能成功產生以下結果:

{item1:16 + 16,item2:17}

使用以下代碼:Stats類存儲兩個字段,但是我不知道如何將兩個字段都添加到數據中

class Stats {
    public Integer data, num;
    public Stats(Integer td, Integer nf) {
        data = td;
        num = nf;
    }
    public Integer getdata(){
        return data;
    }
    public Integer getnum(){
        return num;
    }
}
Map<String, Stats> map = new HashMap<>();
Stream<String> lines = Files.lines(Paths.get(table));
map = lines.map(x -> 
             .collect(Collectors.toMap(
                z -> z[0],
                z -> Integer.parseInt(z[1]),
                (a, b) -> a+b));

上面的代碼僅適用於Map<String, Int>因為我不確定如何使Map<String, Stats>有效。 知道如何僅使用1條管道將第二列上的項目放入地圖嗎?

您首先需要創建一個包含兩個整數的類:

public final class TwoInts {
    private final int data;
    private final int num;

    public TwoInts(int data, int num) { 
        this.data = data;
        this.num = num;
    }

    // getters omitted for brevity
}

然后,您可以重用已有的邏輯,除了使用整數之外,還可以使用TwoInts實例。 因此,您需要能夠將TwoInts的兩個實例加在一起以產生另一個TwoInts實例(就像您通過添加兩個整數來產生一個新的整數一樣):

public final class TwoInts {
    private final int data;
    private final int num;

    public TwoInts(int data, int num) { 
        this.data = data;
        this.num = num;
    }

    public static TwoInts sum(TwoInts first, TwoInts second) {
        return new TwoInts(first.data + second.data, 
                           first.num + second.num);
    }

    // getters omitted for brevity
}

然后你去了:

Stream<String> lines = Files.lines(Paths.get(table));
Map<String, TwoInts> map = 
    lines.map(line -> toArrayOfStrings(line))
         .collect(Collectors.toMap(
              row -> row[0],
              row -> new TwoInts(Integer.parseInt(row[1]), Integer.parseInt(row[2])),
              (a, b) -> TwoInts.sum(a, b));

這是一個實現:

  • 不需要任何額外的課程
  • 適用於任何長度的數值(不只是2)
  • (從技術上來說)只是一行


Stream<String> lines = Stream.of("item1,16,2",
      "item2,17,3",
      "item1,16,5"); // sample input

Map<String, List<Integer>> map = lines.map(s -> s.split(","))
  .collect(Collectors.toMap(a -> a[0],
      a -> Arrays.asList(a).stream()
       .skip(1).map(Integer::parseInt)
        .collect(Collectors.toList()),
      (a, b) -> {for (int i = 0; i < a.size(); i++)
          a.set(i, a.get(i) + b.get(i)); return a;}));

運行以下輸出后打印地圖:

{item2=[17, 3], item1=[32, 7]}

請參閱此代碼的實時演示

首先,您可以使Stats類更加簡化友好的添加合並方法(我也作了些修飾):

class Stats {
    final int data, num;

    public Stats() {
        data = num = 0;
    }

    public Stats(int data, int num) {
        this.data = data;
        this.num = num;
    }

    public Stats merge(Stats stats) {
        return new Stats(this.data+stats.data, this.num+stats.num);
    }

    public int getData(){
        return data;
    }
    public int getNum(){
        return num;
    }

    @Override
    public String toString() {
        return "{" + data + "," + num + "}";
    }
}

現在,您可以使用收集器鏈解決您的任務。 假設您的輸入來自String流,就像在Bohemian答案中那樣:

Stream<String> lines = Stream.of("item1,16,2",
          "item2,17,3",
          "item1,16,5"); // sample input

現在可以以這種方式構建生成的地圖:

Map<String, Stats> map = lines.map(s -> s.split(",")).collect(
    Collectors.groupingBy(a -> a[0], 
    Collectors.mapping(a -> new Stats(Integer.parseInt(a[1]), Integer.parseInt(a[2])), 
    Collectors.reducing(new Stats(), Stats::merge))));
System.out.println(map);

現場演示在這里

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM