如何改进此映射算法

时间:2016-05-25 15:52:59

标签: java algorithm mapping

我有一个n个项目列表,每个项目都有一个产品代码和m个人(可能在多个项目中)。

这样的事情:

items: [
  { code: 'Tuna', people: [ 'Adam', 'Eric' ] },
  { code: 'Corn', people: [ 'Eric' ] },
  ...
]

我想将此映射到不同人员和他们拥有的产品的列表,或类似的东西:

people: {
  Adam: ['Tuna'],
  Eric: ['Tuna', 'Corn']
}

在过去的两个小时里,我一直在努力为自己的直接映射算法提供一个优雅的解决方案。

我在Java 8中这样做,所以流API全部用于争夺。订单并不重要。

这是我目前的最佳努力:

Map<Person, List<String>> partyProductMap = getItems().stream()
        .flatMap(item -> item.getPeople().stream())
        .distinct()
        .collect(Collectors.toMap(
            Function.identity(),
            person -> getItems().stream()
                    .filter(item -> item.getPeople().contains(person))
                    .map(item -> item.getProductCode())
                    .distinct()
                    .collect(Collectors.toList())
        ));

很想听听我如何改进这个想法!

2 个答案:

答案 0 :(得分:2)

我的观点是,最优雅的解决方案是简单的解决方案:

final Map<Person, Set<String>> partyProductMap = new HashMap<>();
for (final Item item : getItems())
    for (final Person person : item.getPeople()) {
        Set<String> codes = partyProductMap.get(person);
        if (codes == null) partyProductMap.put(person, codes = new HashSet<>());
        codes.add(item.code);
    }

注意:这里使用的是Set而不是List

当然,像Item / Person这样的类有hashCode的正确实现,equals并且可能是compareTo

答案 1 :(得分:2)

怎么样:

Map<Person, List<String>> partyProductMap = getItems().stream().
                flatMap(item -> item.getPeople().stream().map(
                        people -> Arrays.asList(
                                people, item.getProductCode()))).
                        collect(Collectors.groupingBy(x -> x.get(0),
                                Collectors.mapping(
                                        x-> x.get(1), Collectors.toList())));