Java 8列表<V>到地图<K,V>中

我想使用Java 8的stream和lambdaexpression式将对象列表转换成Map。

这是我将如何写在Java 7及以下。

private Map<String, Choice> nameMap(List<Choice> choices) { final Map<String, Choice> hashMap = new HashMap<>(); for (final Choice choice : choices) { hashMap.put(choice.getName(), choice); } return hashMap; } 

我可以使用Java 8和Guava轻松完成,但我想知道如何在没有Guava的情况下执行此操作。

在番石榴:

 private Map<String, Choice> nameMap(List<Choice> choices) { return Maps.uniqueIndex(choices, new Function<Choice, String>() { @Override public String apply(final Choice input) { return input.getName(); } }); } 

和Java 8 lambda的番石榴。

 private Map<String, Choice> nameMap(List<Choice> choices) { return Maps.uniqueIndex(choices, c -> c.getName()); } 

基于Collectors文档,它就像下面这样简单:

 Map<String, Choice> result = choices.stream().collect(Collectors.toMap(Choice::getName, Function.identity())); 

如果您的密钥不能保证对列表中的所有元素都是唯一的,则应将其转换为Map<String, List<Choice>>而不是Map<String, Choice>

 Map<String, List<Choice>> result = choices.stream().collect(Collectors.groupingBy(Choice::getName)); 

使用getName()作为键和select本身作为地图的值:

 Map<String, Choice> result = choices.stream().collect(Collectors.toMap(Choice::getName, c -> c)); 

如果您不想使用Collectors.toMap(),那么还有另外一个

 Map<String, Choice> result = choices.stream().collect(HashMap<String, Choice>::new, (m, c) -> m.put(c.getName(), c), (m, u) -> {}); 

如果你不介意使用第三方库( Vavr(以前称为Javaslang) ),你可以使用强大的新的不可变集合:

 // import javaslang.collection.*; Map<String, Choice> map = list.toMap(choice -> Tuple.of(choice.getName(), choice)); 

还有很多方法可以将Java收集转换回来。

请在这里阅读更多有关新的集合 。

免责声明:我是Vavr的创造者。

我试图做到这一点,并发现,使用上面的答案,当使用Functions.identity()的关键到Map,然后我有使用本地方法,如this::localMethodName实际工作,因为input问题。

在这种情况下, Functions.identity()实际上对input做了一些事情,所以这个方法只能通过返回Object并接受一个Object的参数

为了解决这个问题,我最终放弃了Functions.identity()并使用s->s来代替。

所以我的代码,在我的情况下列出目录内的所有目录,并为每个目录使用目录的名称作为映射的关键,然后调用目录名称的方法,并返回项目的集合,如下所示:

 Map<String, Collection<ItemType>> items = Arrays.stream(itemFilesDir.listFiles(File::isDirectory)) .map(File::getName) .collect(Collectors.toMap(s->s, this::retrieveBrandItems)); 

如果您不介意使用第三方库,AOL的独眼巨人反应 lib(披露我是贡献者)有所有JDK集合types的扩展,包括列表和地图 。

 ListX<Choices> choices; Map<String, Choice> map = choices.toMap(c-> c.getName(),c->c); 

还有一个简单的方法

 Map<String,Choice> map = new HashMap<>(); choices.forEach(e->map.put(e.getName(),e)); 
 Map<String, Set<String>> collect = Arrays.asList(Locale.getAvailableLocales()).stream().collect(Collectors .toMap(l -> l.getDisplayCountry(), l -> Collections.singleton(l.getDisplayLanguage()))); 

我使用这个语法

 Map<Integer, List<Choice>> choiceMap = choices.stream().collect(Collectors.groupingBy(choice -> choice.getName())); 

这是StreamEx的解决scheme

 StreamEx.of(choices).toMap(Choice::getName, c -> c); 

您可以使用IntStream创build索引stream,然后将其转换为Map:

 Map<Integer,Item> map = IntStream.range(0,items.size()) .boxed() .collect(Collectors.toMap (i -> i, i -> items.get(i))); 

例如,如果要将对象字段转换为映射:

示例对象:

 class Item{ private String code; private String name; public Item(String code, String name) { this.code = code; this.name = name; } //getters and setters } 

和操作转换列表映射:

 List<Item> list = new ArrayList<>(); list.add(new Item("code1", "name1")); list.add(new Item("code2", "name2")); Map<String,String> map = list.stream() .collect(Collectors.toMap(Item::getCode(), Item::getName())); 
 Map<String,Choice> map=list.stream().collect(Collectors.toMap(Choice::getName, s->s)); 

即使为我服务这个目的,

 Map<String,Choice> map= list1.stream().collect(()-> new HashMap<String,Choice>(), (r,s) -> r.put(s.getString(),s),(r,s) -> r.putAll(s));