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));