[英]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
什么属性,你必须自己调查。
由于你已经覆盖了equals
和hashCode
(错误地,但是勇敢的尝试),我将假设您希望按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"));
所以,这是什么一样,在插入时, a
进Map
,如果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
。 根据您的使用情况,你可能还需要包装返回Collection
与Collections.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.