当前位置: 首页 > 知识库问答 >
问题:

如何将以列表为值的映射拆分为以较小列表为值的映射

平庆
2023-03-14

我有个问题。我在enter中得到了一个csv,其值如下:

99,TEST_ABDC,AB01,0000001
99,TEST_ABDC,AB01,0000002
99,TEST_ABDC,AB01,0000003
99,TEST_ABDC,AB01,0000004
99,TEST_ABDC,AB01,0000005
01,TEST_ABDC,AB01,0000006
01,TEST_ABDC,AB01,0000007
02,TEST_ABDC,AB01,0000007

该文件的名称类似于:AB01_TEST_ABDC_YYYYMMDd.csv

[Bar[99,TEST_ABDC,AB01,0000001], 
Bar[99,TEST_ABDC,AB01,0000002], 
Bar[99,TEST_ABDC,AB01,0000003], 
Bar[99,TEST_ABDC,AB01,0000004], 
Bar[99,TEST_ABDC,AB01,0000005],
Bar[01,TEST_ABDC,AB01,0000006], 
Bar[01,TEST_ABDC,AB01,0000007],
Bar[02,TEST_ABDC,AB01,0000007]]

我需要把它们放到一张地图上,就像:

baz = HashMap<Foo, List<Bar>>

Bar是csv中一行的bean,Foo是由Bar的一些元素创建的bean

现在,我成功地通过CSV的第一列值将列表拆分为一个映射。这给了:

Foo[99, TEST_ABDC, AB01_TEST_ABDC_YYYYMMDD.csv, 0]=[Bar[99,TEST_ABDC,AB01,0000001], Bar[99,TEST_ABDC,AB01,0000002], Bar[99,TEST_ABDC,AB01,0000003], Bar[99,TEST_ABDC,AB01,0000004], Bar[99,TEST_ABDC,AB01,0000005]
Foo[01, TEST_ABDC, AB01_TEST_ABDC_YYYYMMDD.csv, 0]=[Bar[01,TEST_ABDC,AB01,0000006], Bar[01,TEST_ABDC,AB01,0000007]]
Foo[02, TEST_ABDC, AB01_TEST_ABDC_YYYYMMDD.csv, 0]=[Bar[02,TEST_ABDC,AB01,0000007]

我是这样做的:

baz = listBar.stream().distinct()
            .collect(Collectors.groupingBy(b -> b.getFooFromBar(fileAbsolutePath)));

baz必须被csv的第一列和每个第一列值的行的itération拆分。因为它在一个键的列表中不能有超过N个元素。(如下面的例子:2)

Foo[99, TEST_ABDC, AB01_TEST_ABDC_YYYYMMDD.csv, 0]=[Bar[99,TEST_ABDC,AB01,0000001], Bar[99,TEST_ABDC,AB01,0000002]]
Foo[99, TEST_ABDC, AB01_TEST_ABDC_YYYYMMDD.csv, 1]=[Bar[99,TEST_ABDC,AB01,0000003], Bar[99,TEST_ABDC,AB01,0000004]]
Foo[99, TEST_ABDC, AB01_TEST_ABDC_YYYYMMDD.csv, 2]=[Bar[99,TEST_ABDC,AB01,0000005]
Foo[01, TEST_ABDC, AB01_TEST_ABDC_YYYYMMDD.csv, 0]=[Bar[01,TEST_ABDC,AB01,0000006], Bar[01,TEST_ABDC,AB01,0000007]]
Foo[02, TEST_ABDC, AB01_TEST_ABDC_YYYYMMDD.csv, 0]=[Bar[02,TEST_ABDC,AB01,0000007]

我需要拆分列表在n元素最大每个键。我有大量的数据(大约10,000 K+)。它必须分成2K的列表。

请问我怎么做?

共有1个答案

充子航
2023-03-14

我建议首先将您的列表划分为子列表的长度,并获得map >> 。为此,只需将以下方法添加到主类中:

static <T> List<List<T>>  chunk(List<T> list, int n){
    final AtomicInteger counter = new AtomicInteger();

    return new ArrayList<>(list.stream()
                                .collect(Collectors.groupingBy(it -> counter.getAndIncrement() / n))
                                .values());
}

然后将另一个构造函数添加到foo类中,该类接受fooint,通过复制前三个字段创建新的foo,并将新的参数应用到forth字段

public Foo(final Foo foo, int field4) {
    this.field1 = foo.field1;
    this.field2 = foo.field2;
    this.field3 = foo.field3;
    this.field4 = field4;
}

现在,您可以使用上面的代码在baz映射上进行流式传输,将值分块到子列表中,为每个条目创建新的键值对和flatmap并最终收集到map。示例:

    import java.io.IOException;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import lombok.AllArgsConstructor;
import lombok.Getter;

public class Example {

    public static void main(String[] args) throws IOException {
    Map<Foo,List<Bar>> baz =
            Map.of(new Foo("99", "TEST_ABDC", "AB01_TEST_ABDC_YYYYMMDD.csv", 0),
                    List.of(new Bar("99","TEST_ABDC","AB01","0000001"),
                            new Bar("99","TEST_ABDC","AB01","0000002"),
                            new Bar("99","TEST_ABDC","AB01","0000003"),
                            new Bar("99","TEST_ABDC","AB01","0000004"),
                            new Bar("99","TEST_ABDC","AB01","0000005")),

                    new Foo("01", "TEST_ABDC", "AB01_TEST_ABDC_YYYYMMDD.csv", 0),
                    List.of(new Bar("01","TEST_ABDC","AB01","0000006"),
                            new Bar("01","TEST_ABDC","AB01","0000007")),

                    new Foo("02", "TEST_ABDC", "AB01_TEST_ABDC_YYYYMMDD.csv", 0),
                    List.of(new Bar("02","TEST_ABDC","AB01","0000007")));


        Map<Foo,List<Bar>> result =
        baz.entrySet()
            .stream()
            .collect(Collectors.toMap(Map.Entry::getKey, e -> chunk(e.getValue(),2)))
                .entrySet()
                .stream()
                .flatMap(e -> IntStream.range(0, e.getValue().size())
                                       .mapToObj(i -> new AbstractMap.SimpleEntry<>(new Foo(e.getKey(),i),e.getValue().get(i))))
                .collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue));

        result.entrySet().forEach(System.out::println);

    }

    static <T> List<List<T>>  chunk(List<T> list, int n){
        final AtomicInteger counter = new AtomicInteger();

        return new ArrayList<>(list.stream()
                                    .collect(Collectors.groupingBy(it -> counter.getAndIncrement() / n))
                                    .values());
    }

    @AllArgsConstructor
    @Getter
    static class Foo{
        String field1;
        String field2;
        String field3;
        int    field4;

    public Foo(final Foo foo, int field4) {
        this.field1 = foo.field1;
        this.field2 = foo.field2;
        this.field3 = foo.field3;
        this.field4 = field4;
    }

        @Override
        public String toString() {
            return "Foo[" + field1 + ", " + field2 + ", " + field3 + ", " + field4 + ']';
        }
    }

    @AllArgsConstructor
    @Getter
    static class Bar{
        String field1;
        String field2;
        String field3;
        String field4;

        @Override
        public String toString() {
            return "Bar[" + field1 + ", " + field2 + ", " + field3 + ", " + field4 + ']';
        }
    }
}
 类似资料:
  • 我是Mapstruct的新手。我试图将列表转换为地图,我在网上搜索了很多,我有一些解决方案,比如它还没有在mapstruct中实现。如果有人能提供一些替代解决方案,我将很高兴。所有我希望转换映射如下: 现在是否可以使用MapStruct来实现?

  • 我有映射键作为字符串和值作为列表。列表可以有10个唯一值。我需要转换这个映射键为整数和值为列表。示例如下: 输入: 2:“钥匙-1”,“钥匙-2” 3:“钥匙-1”、“钥匙-2”、“钥匙-3” 4:“钥匙-1”、“钥匙-2”、“钥匙-3”

  • 注意: 我不需要创建java对象,因为我只需要检查一些值,但我没有找到任何东西来取消将它们作为通用对象或树或任何东西。像杰克逊的 JsonNode。如果可能的话,让我知道,这样我就可以避免所有这些混乱的对象来映射一切。 现在的问题是: 我不得不解组一个简单的xml,但是结果总是空的。我已经尝试了不同的注释,但是如果它们没有失败,结果就是null。 这似乎是这个问题的相同情况,但使用相同的注释是行不

  • 我有以下代码,希望使用Java8将列表转换为。 当我尝试将列表中的单个值映射为映射的键时,我得到了一个错误。

  • 问题内容: 我正在寻找一种将python列表轻松分成两半的方法。 这样,如果我有一个数组: 我将能够得到: 问题答案: 如果需要功能:

  • 我有一个包含两个重要属性的列表,和。实例可以共享值,但具有唯一的s。 我想把这个List转换成一个Map,这样共享一个Bar的所有实例的唯一的都被放在映射到那个共享的的Set中。 我自己的功能印章还没有被证明能胜任这项任务。我试图同时和List,但是当试图将不同的参数实现为lambdas时,被类型问题绊倒了。 尝试使用Collect 不完整,编译器无法确定m或foo和Foo::getBaz的类型。