Java 8将<v>列入Map <k,v =“”> </k,> </v>

时间:2013-12-03 23:18:49

标签: java lambda java-8 java-stream

我想使用Java 8的流和lambdas将对象列表转换为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();
        }
    });
}

Guava with Java 8 lambdas。

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

22 个答案:

答案 0 :(得分:1255)

基于Collectors documentation,它很简单:

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

答案 1 :(得分:268)

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

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

答案 2 :(得分:135)

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

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

答案 3 :(得分:19)

如果您不想使用Collectors.toMap()

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

答案 4 :(得分:18)

列出的大多数答案中,错过了列表中有重复项的情况。在这种情况下,答案将抛出IllegalStateException。同样,请参考下面的代码以处理列表重复项

public Map<String, Choice> convertListToMap(List<Choice> choices) {
    return choices.stream()
        .collect(Collectors.toMap(Choice::getName, choice -> choice,
            (oldValue, newValue) -> newValue));
  }

答案 5 :(得分:15)

  

以简单的方式再添一个选项

Map<String,Choice> map = new HashMap<>();
choices.forEach(e->map.put(e.getName(),e));

答案 6 :(得分:15)

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

示例对象:

class Item{
        private String code;
        private String name;

        public Item(String code, String name) {
            this.code = code;
            this.name = name;
        }

        //getters and setters
    }

操作转换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));

答案 7 :(得分:10)

如果您不介意使用第三方库,AOL的cyclops-react lib(披露我是贡献者)具有所有JDK Collection类型的扩展名,包括List和{{3} }。

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

答案 8 :(得分:8)

我试图这样做,发现使用上面的答案,当使用Functions.identity()作为地图的关键字时,我遇到了使用像this::localMethodName这样的本地方法实际工作的问题因为打字问题。

Functions.identity()实际上对这种情况下的输入做了些什么,所以该方法只能通过返回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));

答案 9 :(得分:7)

您可以使用IntStream创建索引流,然后将它们转换为Map:

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

答案 10 :(得分:4)

我使用这种语法

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

答案 11 :(得分:4)

我将写出如何使用泛型控制反转将列表转换为地图的方法。只是通用方法!

也许,我们有整数列表对象列表。因此,问题如下:什么是键地图?

创建界面

public interface KeyFinder<K, E> {
    K getKey(E e);
}

现在使用控制反转:

  static <K, E> Map<K, E> listToMap(List<E> list, KeyFinder<K, E> finder) {
        return  list.stream().collect(Collectors.toMap(e -> finder.getKey(e) , e -> e));
    }

例如,如果我们有book对象,则该类是为地图选择键

public class BookKeyFinder implements KeyFinder<Long, Book> {
    @Override
    public Long getKey(Book e) {
        return e.getPrice()
    }
}

答案 12 :(得分:3)

Map<String, Set<String>> collect = Arrays.asList(Locale.getAvailableLocales()).stream().collect(Collectors
                .toMap(l -> l.getDisplayCountry(), l -> Collections.singleton(l.getDisplayLanguage())));

答案 13 :(得分:2)

可以使用流来执行此操作。为了消除显式使用Collectors的需要,可以静态导入toMap(如有效Java建议的第三版所述)。

import static java.util.stream.Collectors.toMap;

private static Map<String, Choice> nameMap(List<Choice> choices) {
    return choices.stream().collect(toMap(Choice::getName, it -> it));
}

答案 14 :(得分:1)

仅在评论中出现另一种可能性:

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

如果要将子对象的参数用作键,则很有用:

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

答案 15 :(得分:1)

以下是StreamEx

的解决方案
StreamEx.of(choices).toMap(Choice::getName, c -> c);

答案 16 :(得分:0)

这可以通过两种方式完成。让人成为我们将用来演示它的课程。

public class Person {

    private String name;
    private int age;

    public String getAge() {
        return age;
    }
}

成为要转换为地图的人员列表

1.在列表中使用简单的foreach和Lambda表达式

Map<Integer,List<Person>> mapPersons = new HashMap<>();
persons.forEach(p->mapPersons.put(p.getAge(),p));

2.在给定列表上定义的Stream上使用收集器。

 Map<Integer,List<Person>> mapPersons = 
           persons.stream().collect(Collectors.groupingBy(Person::getAge));

答案 17 :(得分:0)

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

答案 18 :(得分:0)

If every new value for the same key name has to be overidden
then below will be the code :

    public Map<String, Choice> 
      convertListToMap(List<Choice> choices) {
     return choices.stream()
       .collect(Collectors.toMap(Choice::getName, 
      Function.identity(),
            (oldValue, newValue) -> newValue));
      }

If all choices have to be grouped in a list for a name then 
below will be the code:

      public Map<String, Choice> 
       convertListToMap(List<Choice> choices) {
       return choices.stream().collect(Collectors.groupingBy(Choice::getName));
  }

答案 19 :(得分:0)

List<V> choices; // your list
Map<K,V> result = choices.stream().collect(Collectors.toMap(choice::getKey(),choice));
//assuming class "V" has a method to get the key, this method must handle case of duplicates too and provide a unique key.

答案 20 :(得分:0)

作为guava的替代者,可以使用kotlin-stdlib

private Map<String, Choice> nameMap(List<Choice> choices) {
    return CollectionsKt.associateBy(choices, Choice::getName);
}

答案 21 :(得分:-2)

String array[] = {"ASDFASDFASDF","AA", "BBB", "CCCC", "DD", "EEDDDAD"};
    List<String> list = Arrays.asList(array);
    Map<Integer, String> map = list.stream()
            .collect(Collectors.toMap(s -> s.length(), s -> s, (x, y) -> {
                System.out.println("Dublicate key" + x);
                return x;
            },()-> new TreeMap<>((s1,s2)->s2.compareTo(s1))));
    System.out.println(map);

公开密钥AA {12 = ASDFASDFASDF,7 = EEDDDAD,4 = CCCC,3 = BBB,2 = AA}