我有两种方法可以从Map
个对象中创建一个List
:
private Map<String, Foo> getFooMap(List<Foo> oos) {
return foos.stream()
.map(foo -> new AbstractMap.SimpleEntry<>(foo.getText(), foo))
.collect(Collectors.toMap(
AbstractMap.SimpleEntry::getKey,
AbstractMap.SimpleEntry::getValue));
}
private Map<String, Bar> getBarMap(List<Bar> bars) {
return bars.stream()
.map(bar -> new AbstractMap.SimpleEntry<>(bar.getName(), bar))
.collect(Collectors.toMap(
AbstractMap.SimpleEntry::getKey,
AbstractMap.SimpleEntry::getValue));
}
我想创建一个更通用的函数,因为它们几乎是相同的。唯一的区别(对象类型除外)是创建密钥的方法:foo.getText()
与bar.getName()
。有没有办法将它们转换为单一方法?
答案 0 :(得分:4)
当然,只需传递'y': 2012
'freq': 4,
'y': 2011
'freq': 6
即可提取密钥。另外,您之间不需要Function
:
Entry
您可以这样称呼它:
static <T, K> Map<K, T> toMap(List<T> list, Function<? super T, K> getKey) {
return list.stream()
.collect(Collectors.toMap(getKey, Function.identity()));
}
答案 1 :(得分:0)
请参阅下面的评论。
// Alternate to "AbstractMap.SimpleEntry". This may seem redundant,
// but one rather should avoid coupling one's implementation to other
// implementations.
public class SimpleEntry<K, V> implements Map.Entry<K, V> {
public SimpleEntry(K k, V v) {
this.k = k;
this.v = v;
}
private K k;
public K getKey() { return k; }
private V v;
@Override
public V getValue() { return v; }
@Override
public V setValue(V v) { V oldV = this.v; this.v = v; return oldV; }
}
// A representative element class.
public static class Foo {
public String getText() {
return "text";
}
}
// The mapping example, changed to use simple entry, and to use "Map.Entry" based functions
// as the parameters to Collectors.toMap. Map.Entry is a public interface; AbstractMap.SimpleEntry
// is an implementation type. Note that since AbstractMap.SimpleEntry implements Map.Entry, this
// still works.
public Map<String, Foo> getFooMap(List<Foo> foos) {
return foos.stream()
.map( foo -> new SimpleEntry<String, Foo>(foo.getText(), foo) )
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
// An attempt to generalize the element and key types. This fails because 'foo.getText()'
// is no longer understood.
public <K, V> Map<K, V> getMap1(List<V> foos) {
return foos.stream()
.map( foo -> new SimpleEntry<K, V>(foo.getText(), foo) )
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
// Second attempt: The prior 'foo.getText()' is replaced with function 'keyGetter',
// which is a new parameter to the method.
public <K, V> Map<K, V> getMap2(List<V> foos, Function<V, K> keyGetter) {
return foos.stream()
.map( foo -> new SimpleEntry<K, V>(keyGetter.apply(foo), foo) )
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}