I want to translate a List of objects into a Map using Java 8's streams and lambdas.
我想用Java 8的流和lambdas将一个对象列表转换成映射。
This is how I would write it in Java 7 and below.
这就是我如何在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;
}
I can accomplish this easily using Java 8 and Guava but I would like to know how to do this without Guava.
我可以很容易地用Java 8和Guava来完成这个任务,但是我想知道如何在没有Guava的情况下做到这一点。
In 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();
}
});
}
And Guava with Java 8 lambdas.
和Java 8的番石榴。
private Map<String, Choice> nameMap(List<Choice> choices) {
return Maps.uniqueIndex(choices, Choice::getName());
}
14 个解决方案
#1
961
Based on Collectors
documentation it's as simple as:
基于收集器的文档,它非常简单:
Map<String, Choice> result =
choices.stream().collect(Collectors.toMap(Choice::getName,
Function.identity()));
#2
189
If your key is NOT guaranteed to be unique for all elements in the list, you should convert it to a Map<String, List<Choice>>
instead of a Map<String, Choice>
如果您的键不能保证列表中的所有元素都是惟一的,那么您应该将其转换为Map
Map<String, List<Choice>> result =
choices.stream().collect(Collectors.groupingBy(Choice::getName));
#3
99
Use getName() as the key and choice itself as the value of the map:
使用getName()作为键和选择本身作为映射的值:
Map<String, Choice> result =
choices.stream().collect(Collectors.toMap(Choice::getName, c -> c));
#4
11
Here's another one in case you don't want to use Collectors.toMap()
这是另一个,以防你不想使用Collectors.toMap()
Map<String, Choice> result =
choices.stream().collect(HashMap<String, Choice>::new,
(m, c) -> m.put(c.getName(), c),
(m, u) -> {});
#5
10
If you don't mind to use a 3rd party lib (Vavr(formerly known as Javaslang)) you could use powerful new immutable collections:
如果您不介意使用第三方lib (Vavr(以前称为Javaslang)),您可以使用强大的新不可变集合:
// import javaslang.collection.*;
Map<String, Choice> map = list.toMap(choice -> Tuple.of(choice.getName(), choice));
There are also many methods to convert Java collections forth and back.
还有许多方法可以将Java集合来回转换。
Please read more about the new collections here.
请阅读更多关于这里的新收藏品。
Disclaimer: I'm the creator of Vavr.
免责声明:我是Vavr的创建者。
#6
8
If you don't mind using 3rd party libraries, AOL's cyclops-react lib (disclosure I am a contributor) has extensions for all JDK Collection types, including List and Map.
如果您不介意使用第三方库,AOL的cyclops-react lib(我是一个贡献者)对所有JDK集合类型都有扩展,包括列表和映射。
ListX<Choices> choices;
Map<String, Choice> map = choices.toMap(c-> c.getName(),c->c);
#7
8
One more option in simple way
还有一个简单的选择。
Map<String,Choice> map = new HashMap<>();
choices.forEach(e->map.put(e.getName(),e));
#8
7
I was trying to do this and found that, using the answers above, when using Functions.identity()
for the key to the Map, then I had issues with using a local method like this::localMethodName
to actually work because of typing issues.
我试图这样做,并发现,在使用函数.identity()作为映射的键时,我使用了这样的本地方法::localMethodName实际上是由于键入问题而工作的。
Functions.identity()
actually does something to the typing in this case so the method would only work by returning Object
and accepting a param of Object
identity()实际上对这种情况下的类型进行了一些操作,因此该方法只能通过返回对象并接受对象的一个param来工作。
To solve this, I ended up ditching Functions.identity()
and using s->s
instead.
为了解决这个问题,我放弃了函数。identity()和使用s->s。
So my code, in my case to list all directories inside a directory, and for each one use the name of the directory as the key to the map and then call a method with the directory name and return a collection of items, looks like:
因此,我的代码,在我的例子中列出了目录中的所有目录,对于每个目录,都使用目录的名称作为映射的键,然后调用一个带有目录名的方法并返回一个条目集合,如下所示:
Map<String, Collection<ItemType>> items = Arrays.stream(itemFilesDir.listFiles(File::isDirectory))
.map(File::getName)
.collect(Collectors.toMap(s->s, this::retrieveBrandItems));
#9
4
I use this syntax
我用这个语法
Map<Integer, List<Choice>> choiceMap =
choices.stream().collect(Collectors.groupingBy(choice -> choice.getName()));
#10
4
For example, if you want convert object fields to map:
例如,如果您希望将对象字段转换为映射:
Example object:
例对象:
class Item{
private String code;
private String name;
public Item(String code, String name) {
this.code = code;
this.name = name;
}
//getters and setters
}
And operation convert List To Map:
操作转换列表为:
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()));
#11
3
Map<String, Set<String>> collect = Arrays.asList(Locale.getAvailableLocales()).stream().collect(Collectors
.toMap(l -> l.getDisplayCountry(), l -> Collections.singleton(l.getDisplayLanguage())));
#12
3
You can create a Stream of the indices using an IntStream and then convert them to a Map :
您可以使用一个IntStream创建一个索引流,然后将它们转换为映射:
Map<Integer,Item> map =
IntStream.range(0,items.size())
.boxed()
.collect(Collectors.toMap (i -> i, i -> items.get(i)));
#13
1
Here is solution by StreamEx
这里是StreamEx的解决方案。
StreamEx.of(choices).toMap(Choice::getName, c -> c);
#14
-1
Map<String,Choice> map=list.stream().collect(Collectors.toMap(Choice::getName, s->s));
Even serves this purpose for me,
甚至为我服务,
Map<String,Choice> map= list1.stream().collect(()-> new HashMap<String,Choice>(),
(r,s) -> r.put(s.getString(),s),(r,s) -> r.putAll(s));
#1
961
Based on Collectors
documentation it's as simple as:
基于收集器的文档,它非常简单:
Map<String, Choice> result =
choices.stream().collect(Collectors.toMap(Choice::getName,
Function.identity()));
#2
189
If your key is NOT guaranteed to be unique for all elements in the list, you should convert it to a Map<String, List<Choice>>
instead of a Map<String, Choice>
如果您的键不能保证列表中的所有元素都是惟一的,那么您应该将其转换为Map
Map<String, List<Choice>> result =
choices.stream().collect(Collectors.groupingBy(Choice::getName));
#3
99
Use getName() as the key and choice itself as the value of the map:
使用getName()作为键和选择本身作为映射的值:
Map<String, Choice> result =
choices.stream().collect(Collectors.toMap(Choice::getName, c -> c));
#4
11
Here's another one in case you don't want to use Collectors.toMap()
这是另一个,以防你不想使用Collectors.toMap()
Map<String, Choice> result =
choices.stream().collect(HashMap<String, Choice>::new,
(m, c) -> m.put(c.getName(), c),
(m, u) -> {});
#5
10
If you don't mind to use a 3rd party lib (Vavr(formerly known as Javaslang)) you could use powerful new immutable collections:
如果您不介意使用第三方lib (Vavr(以前称为Javaslang)),您可以使用强大的新不可变集合:
// import javaslang.collection.*;
Map<String, Choice> map = list.toMap(choice -> Tuple.of(choice.getName(), choice));
There are also many methods to convert Java collections forth and back.
还有许多方法可以将Java集合来回转换。
Please read more about the new collections here.
请阅读更多关于这里的新收藏品。
Disclaimer: I'm the creator of Vavr.
免责声明:我是Vavr的创建者。
#6
8
If you don't mind using 3rd party libraries, AOL's cyclops-react lib (disclosure I am a contributor) has extensions for all JDK Collection types, including List and Map.
如果您不介意使用第三方库,AOL的cyclops-react lib(我是一个贡献者)对所有JDK集合类型都有扩展,包括列表和映射。
ListX<Choices> choices;
Map<String, Choice> map = choices.toMap(c-> c.getName(),c->c);
#7
8
One more option in simple way
还有一个简单的选择。
Map<String,Choice> map = new HashMap<>();
choices.forEach(e->map.put(e.getName(),e));
#8
7
I was trying to do this and found that, using the answers above, when using Functions.identity()
for the key to the Map, then I had issues with using a local method like this::localMethodName
to actually work because of typing issues.
我试图这样做,并发现,在使用函数.identity()作为映射的键时,我使用了这样的本地方法::localMethodName实际上是由于键入问题而工作的。
Functions.identity()
actually does something to the typing in this case so the method would only work by returning Object
and accepting a param of Object
identity()实际上对这种情况下的类型进行了一些操作,因此该方法只能通过返回对象并接受对象的一个param来工作。
To solve this, I ended up ditching Functions.identity()
and using s->s
instead.
为了解决这个问题,我放弃了函数。identity()和使用s->s。
So my code, in my case to list all directories inside a directory, and for each one use the name of the directory as the key to the map and then call a method with the directory name and return a collection of items, looks like:
因此,我的代码,在我的例子中列出了目录中的所有目录,对于每个目录,都使用目录的名称作为映射的键,然后调用一个带有目录名的方法并返回一个条目集合,如下所示:
Map<String, Collection<ItemType>> items = Arrays.stream(itemFilesDir.listFiles(File::isDirectory))
.map(File::getName)
.collect(Collectors.toMap(s->s, this::retrieveBrandItems));
#9
4
I use this syntax
我用这个语法
Map<Integer, List<Choice>> choiceMap =
choices.stream().collect(Collectors.groupingBy(choice -> choice.getName()));
#10
4
For example, if you want convert object fields to map:
例如,如果您希望将对象字段转换为映射:
Example object:
例对象:
class Item{
private String code;
private String name;
public Item(String code, String name) {
this.code = code;
this.name = name;
}
//getters and setters
}
And operation convert List To Map:
操作转换列表为:
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()));
#11
3
Map<String, Set<String>> collect = Arrays.asList(Locale.getAvailableLocales()).stream().collect(Collectors
.toMap(l -> l.getDisplayCountry(), l -> Collections.singleton(l.getDisplayLanguage())));
#12
3
You can create a Stream of the indices using an IntStream and then convert them to a Map :
您可以使用一个IntStream创建一个索引流,然后将它们转换为映射:
Map<Integer,Item> map =
IntStream.range(0,items.size())
.boxed()
.collect(Collectors.toMap (i -> i, i -> items.get(i)));
#13
1
Here is solution by StreamEx
这里是StreamEx的解决方案。
StreamEx.of(choices).toMap(Choice::getName, c -> c);
#14
-1
Map<String,Choice> map=list.stream().collect(Collectors.toMap(Choice::getName, s->s));
Even serves this purpose for me,
甚至为我服务,
Map<String,Choice> map= list1.stream().collect(()-> new HashMap<String,Choice>(),
(r,s) -> r.put(s.getString(),s),(r,s) -> r.putAll(s));