繁体   English   中英

Map的实现意味着每个键可能只包含1个值...但我需要1个键可以存储 <Any Big Number> 值

[英]The implementation of Map implies that each key may contains only 1 value… But i need that 1 key could store <Any Big Number> values

例如......邻接列表实现

public class Vertex {
    String name;
    boolean visited;
    public Vertex(String name) {
        this.name=name;
        visited=false;
    }
    public int hashCode() {
        return name.hashCode();
    }
    public boolean equals(Object ob) {
        return hashCode()==ob.hashCode();
    }
    public String toString() {
        return name;
    }
}

主要课程

import java.util.*;
import java.io.*;
public class Main {
    public static void main(String[] args) {
        PrintWriter pw=new PrintWriter(System.out);
        Map<Vertex,Vertex> m=new HashMap();
        m.put(new Vertex("a"), new Vertex("b"));// a ---> b
        m.put(new Vertex("a"), new Vertex("c"));// a ---> c
        m.put(new Vertex("a"), new Vertex("d"));// a ---> d
        pw.println("All vertex from: ");
        for (Vertex vert_from:m.keySet()) {
            pw.print(vert_from+" ");
        }
        pw.println();
        pw.println("All vertices to: ");
        for (Vertex vert_to:m.values()) {
            pw.print(vert_to+" ");
        }
        pw.close();
    }
}

它输出:
所有顶点来自:
一个
所有顶点:
d
但我需要“所有顶点:bcd”
我该如何解决这个问题?

Map确实为每个键存储单个值。 但是,您可以将一个集合存储在值中,例如Set

Map<Vertex, Set<Vertex>> m = new HashMap<>();
Set<Vertex> set = new HashSet<>();
set.add(new Vertex("b"));
set.add(new Vertex("c"));
set.add(new Vertex("d"));
m.add (new Vertex("a"), set);

或者,您可以使用此概念的常见实现之一,例如Apache Commons Collections的MultiValueMap或Guava的HashMultiMap

您要求的是“多地图”。

如果您使用的是Java 8,那么这非常简洁,首先您需要Map<Vertex, Collection<Vertex>> 我不知道你需要从Collection什么属性,你必须自己调查。

由于你已经覆盖了equalshashCode (错误地,但是勇敢的尝试),我将假设您希望按name使项目唯一。 我还假设订单很重要,所以LinkedHashSet似乎是一个不错的选择。

final Map<Vertex, Collection<Vertex>> graph = new HashMap<>();

现在,要向Map添加项目,我们需要首先确保该键的Collection不为null 这正是新Map.computeIfAbsent用武之地。

final Vertex a = new Vertex("a");
graph.computeIfAbsent(a, v -> new LinkedHashSet<>()).add(new Vertex("b"));
graph.computeIfAbsent(a, v -> new LinkedHashSet<>()).add(new Vertex("c"));
graph.computeIfAbsent(a, v -> new LinkedHashSet<>()).add(new Vertex("d"));

所以,这是什么一样,在插入时, aMap ,如果Collection该键为null ,计算它的新值。

现在获取密钥的所有值:

Collection<Vertex> values = graph.get(a);

您可以将Map<Vertex, Collection<Vertex>>包装在某种Graph类中,以隐藏实现细节并使用更简洁的代码:

class Graph {
    final Map<Vertex, Collection<Vertex>> graph = new HashMap<>();

    public void put(final Vertex key, final Vertex value) {
        graph.computeIfAbsent(key, k -> new LinkedHashSet<>()).add(value);
    }

    public Collection<Vertex> get(final Vertex key) {
        return Optional.ofNullable(graph.get(key)).orElse(Collections.EMPTY_SET);
    }
}

如果Map没有键,则还处理返回空集合而不是null 根据您的使用情况,你可能还需要包装返回CollectionCollections.unmodifiableCollection以防止不必要的修改:

public Collection<Vertex> get(final Vertex key) {
    return Optional.ofNullable(graph.get(key))
            .map(Collections::unmodifiableCollection)
            .orElse(Collections.EMPTY_SET);
}

如果您不反对外部库,也可以使用Guava Multimap

使用Multimap解决您的问题,可以这样编写:

public static void main(String[] args) {
    PrintWriter pw=new PrintWriter(System.out);
    ListMultimap<Vertex,Vertex> m= ArrayListMultimap.create();

    Vertex a = new Vertex("a"); // it's better to create each object once
    Vertex b = new Vertex("b");
    Vertex c = new Vertex("c");
    Vertex d = new Vertex("d");

    m.put(a,b);// a ---> b
    m.put(a,c);// a ---> c
    m.put(a,d);// a ---> d
    pw.println("All vertex from: ");
    for (Vertex vert_from:m.keySet()) { //exactly the same as in your code
        pw.print(vert_from+" ");
    }
    pw.println();
    pw.println("All vertices to: ");
    for (Vertex vert_to:m.values()) { //exactly the same as in your code
        pw.print(vert_to+" ");
    }
    pw.close();
}

要使用Guava,只需从此处下载最新的jar并将其添加到您的库中。


说明:

根据定义,每个Java Map都有一个键和一个值。

但是,您可以使用Collection(如List)或Array作为值。 这样,您的地图将被定义为:

Map<Vertex, List<Vertex>> m = new HashMap<>();

每次要将元素value添加到顶点key列表时,都可以这样做:

List<Vertex> list = m.get(key);
if (list == null) {
    list = new ArrayList<>();
}
list.add(value);

更简单的方法是使用Guava的Multimaps 它与Map相同,但值为Collection。 所以, ArrayListMultimap就像我上面描述的那样。 使用它的方式虽然简单得多:

ListMultimap<Vertex, Vertex> m = ArrayListMultimap.create();
m.put(key, value1);
m.put(key, value2); //adds value2 to the key, which also contains value1
....

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM