使用不同的内部方法调用泛化方法

时间:2019-03-20 19:37:20

标签: java

我有两种方法可以从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()。有没有办法将它们转换为单一方法?

2 个答案:

答案 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));
}