자바 8 목록 지도로
Java 8의 스트림과 람다를 사용하여 객체 목록을 맵으로 변환하고 싶습니다.
이것이 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 람다가 포함 된 Guava.
private Map<String, Choice> nameMap(List<Choice> choices) {
return Maps.uniqueIndex(choices, Choice::getName);
}
Collectors
문서에 따르면 다음 과 같이 간단합니다.
Map<String, Choice> result =
choices.stream().collect(Collectors.toMap(Choice::getName,
Function.identity()));
키가 목록의 모든 요소에 대해 고유하다고 보장 되지 않는 경우 키 를 a Map<String, List<Choice>>
대신 a로 변환해야 합니다.Map<String, Choice>
Map<String, List<Choice>> result =
choices.stream().collect(Collectors.groupingBy(Choice::getName));
getName()
키로 사용 하고 Choice
그 자체를 맵의 값으로 사용 :
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) -> {});
나열된 답변의 대부분은 목록에 중복 항목이 있는 경우 누락 됩니다 . 이 경우 대답이 던져 IllegalStateException
집니다. 목록 중복 도 처리 하려면 아래 코드 를 참조하십시오 .
public Map<String, Choice> convertListToMap(List<Choice> choices) {
return choices.stream()
.collect(Collectors.toMap(Choice::getName, choice -> choice,
(oldValue, newValue) -> newValue));
}
예를 들어 개체 필드를 매핑으로 변환하려는 경우 :
예제 개체 :
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 = new HashMap<>();
choices.forEach(e->map.put(e.getName(),e));
타사 라이브러리를 사용해도 괜찮다면 AOL의 cyclops-react lib (공개 자 공개)에는 List 및 Map을 포함한 모든 JDK 컬렉션 유형에 대한 확장이 있습니다 .
ListX<Choices> choices;
Map<String, Choice> map = choices.toMap(c-> c.getName(),c->c);
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.
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
To solve this, I ended up ditching Functions.identity()
and using s->s
instead.
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));
You can create a Stream of the indices using an IntStream and then convert them to a Map :
Map<Integer,Item> map =
IntStream.range(0,items.size())
.boxed()
.collect(Collectors.toMap (i -> i, i -> items.get(i)));
I use this syntax
Map<Integer, List<Choice>> choiceMap =
choices.stream().collect(Collectors.groupingBy(choice -> choice.getName()));
I will write how to convert list to map using generics and inversion of control. Just universal method!
Maybe we have list of Integers or list of objects. So the question is the following: what should be key of the map?
create interface
public interface KeyFinder<K, E> {
K getKey(E e);
}
now using inversion of control:
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));
}
For example, if we have objects of book , this class is to choose key for the map
public class BookKeyFinder implements KeyFinder<Long, Book> {
@Override
public Long getKey(Book e) {
return e.getPrice()
}
}
Map<String, Set<String>> collect = Arrays.asList(Locale.getAvailableLocales()).stream().collect(Collectors
.toMap(l -> l.getDisplayCountry(), l -> Collections.singleton(l.getDisplayLanguage())));
It's possible to use streams to do this. To remove the need to explicitly use Collectors
, it's possible to import toMap
statically (as recommended by Effective Java, third edition).
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));
}
Here is solution by StreamEx
StreamEx.of(choices).toMap(Choice::getName, c -> c);
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));
This can be done in 2 ways. Let person be the class we are going to use to demonstrate it.
public class Person {
private String name;
private int age;
public String getAge() {
return age;
}
}
Let persons be the list of Persons to be converted to the map
1.Using Simple foreach and a Lambda Expression on the List
Map<Integer,List<Person>> mapPersons = new HashMap<>();
persons.forEach(p->mapPersons.put(p.getAge(),p));
2.Using Collectors on Stream defined on the given List.
Map<Integer,List<Person>> mapPersons =
persons.stream().collect(Collectors.groupingBy(Person::getAge));
If every new value for the same key name has to be overridden:
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:
public Map < String, Choice > convertListToMap(List < Choice > choices) {
return choices.stream().collect(Collectors.groupingBy(Choice::getName));
}
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.
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);
Dublicate key AA {12=ASDFASDFASDF, 7=EEDDDAD, 4=CCCC, 3=BBB, 2=AA}
참고URL : https://stackoverflow.com/questions/20363719/java-8-listv-into-mapk-v
'development' 카테고리의 다른 글
$ scope. $ emit 및 $ scope. $ on 작업 (0) | 2020.09.28 |
---|---|
값으로 목록 요소를 삭제하는 간단한 방법이 있습니까? (0) | 2020.09.28 |
git이 프록시 서버로 작업하기 (0) | 2020.09.28 |
ID 일치를 기반으로 한 테이블에서 다른 테이블로 SQL 업데이트 (0) | 2020.09.28 |
HTML5 / Canvas / JavaScript를 사용하여 브라우저 내 스크린 샷 찍기 (0) | 2020.09.28 |