如何使用 RxJava 和 Lambda 表达式一次在地图中插入两条记录

How to insert two records in map at a time using RxJava and Lambda expressions

我有一个记录列表,其中每条记录都有两个主键 Primary Id 和 Alternate Id。我想制作一个地图,通过它我可以使用主 ID 或使用 RxJava 操作的备用 ID 访问已处理的记录。

当前实施:

ImmutableMap.Builder<String, Record> mapBuilder = new ImmutableMap.Builder<>();
      fetchRecords()
          .forEach(
              record -> {
                parsedRecord = dosomething(record);
                mapBuilder.put(parsedRecord.getPrimaryId(), parsedRecord);
                mapBuilder.put(parsedRecord.getAlternativeId(), parsedRecord);
              });
      return mapBuilder.build();

我希望它看起来像:

fetchRecords().stream()
    .map(doSomething)
    .collect(Collectors.toMap(RecordData::getPrimaryId, Function.identity()));
// Need to add this as well
.collect(Collectors.toMap(RecordData::getAlterantiveId, Function.identity()));

只是想知道是否可以通过 fetchRecords() 一次传递将辅助 ID 添加到记录映射中。

我不熟悉 rx-java 但这可能会提供一个起点。创建自定义收集器以添加这两个键。这是一个非常基本的收集器,除了使用提供的最后一个之外,不处理重复键。我只是使用 Java 15 中引入的新 record 功能来创建一个不可变的 "class"。对于常规 class.

这将以相同的方式工作
record ParsedRecord(String getPrimaryId,
        String getAlternativeId, String someValue) {
    @Override
    public String toString() {
        return someValue;
    }
}

Map<String, ParsedRecord> map = records.stream()
        .collect(twoKeys(ParsedRecord::getPrimaryId,
                ParsedRecord::getAlternativeId, p -> p));

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

打印以下内容:

A=value1
B=value1
C=value2
D=value2

收藏家来了。它本质上是 toMap 的简化版本,使用两个键而不是一个。

private static <T, K, V> Collector<T, ?, Map<K, V>> twoKeys(
        Function<T, K> keyMapper1, Function<T, K> keyMapper2,
        Function<T, V> valueMapper) {

    return Collector.of(
        () -> new HashMap<K, V>(),
        (m, r) -> {
        V v = valueMapper.apply(r);
        m.put(keyMapper1.apply(r),v);
        m.put(keyMapper2.apply(r),v);
    }, (m1, m2) -> {
        m1.putAll(m2);
        return m1;
    }, Characteristics.UNORDERED);
}

或者保持简单高效。

Map<String, ParsedRecord> map = new HashMap<>();
for(ParsedRecord pr : records) {
    map.put(pr.getPrimaryId(), pr);
    map.put(pr.getAlternativeId(), pr);
}