英文:
Return a hashmap derived from an arraylist
问题
public HashMap<String, HashSet<Integer>> getStopsAndBusNumbers() {
HashMap<String, HashSet<Integer>> map = new HashMap<>();
for (String stop : routes.get(32)) {
map.put(stop, getBusesStoppingHere(stop));
}
for (String stop : routes.get(13)) {
if (!map.containsKey(stop)) {
map.put(stop, getBusesStoppingHere(stop));
} else {
map.get(stop).addAll(getBusesStoppingHere(stop));
}
}
return map;
}
英文:
I am trying to return a HashMap
with the bus numbers and their stops.
I have already created a method to return a HashSet
by passing one of the stops into it.
I feel like it can all come together, but I keep going around in circles.
public class BusRoutes
{
public HashMap<Integer,ArrayList<String>> routes;
public void populateRoutes()
{
ArrayList<String> stops = new ArrayList<>();
stops.add("High Street");
stops.add("Acacia Avenue");
stops.add("Brown Street");
stops.add("Broadway");
stops.add("Station");
routes.put(32, stops);
ArrayList<String> stops1 = new ArrayList<>();
stops1.add("High Street");
stops1.add("Hospital");
stops1.add("Brown Street");
stops1.add("School");
stops1.add("Station");
routes.put(13, stops1);
}
public BusRoutes() {
routes = new HashMap<>();
reader = new InputReader();
populateRoutes();
}
public void printRoute(int busNum) {
System.out.println("Bus number " + busNum + " route:");
for (int i = 0; i < routes.get(busNum).size(); i++) {
System.out.println(routes.get(busNum).get(i));
}
}
public void printAllRoutes() {
for (int i = 0; i < routes.size(); i++) {
System.out.println(routes.get(i));
}
}
public HashSet<Integer> getBusesStoppingHere(String aStop) {
HashSet<Integer> busNumbers = new HashSet<>();
for (Integer key : routes.keySet()) {
if (routes.get(key).contains(aStop)) {
busNumbers.add(key);
}
}
return busNumbers;
}
public HashMap<String, HashSet<Integer>> getStopsAndBusNumbers() {
HashMap<String, HashSet<Integer>> map = new HashMap<String, HashSet<Integer>>();
// This is where I am stuck
return map;
}
}
答案1
得分: 2
我想要返回一个从路线中得到的地图,在这个地图中,包含在路线地图中的每个站点都是一个键,每个值都是一个包含该站点的公交车号的集合。
我相信这会实现你想要的功能。
- 首先分配一个记录以保存站点和公交车号。
Map.entry()
方法也可以使用,但记录不会占用额外内存,并且给参数赋予了有意义的名称。 - 然后使用
flatMap()
,遍历现有地图的entrySet()
。 - 然后,使用
flatMap()
,遍历entrySet
的站点。每个站点和相关的公交车将被映射到记录中。 - 现在,只需将每个站点分组到一个公交车集合中。
- Collectors.groupingBy 还可以使用另一个收集器,这里是 Collectors.mapping,用于从
Pair
实例中提取公交车号,然后放入一个集合中。
record Pair(String getStop, Integer getBus) {}
public Map<String, Set<Integer>> getStopsAndBusNumbers(Map<Integer, List<String>> map) {
return map.entrySet()
.stream()
.flatMap(e->e.getValue().stream().map(stop->new Pair(stop, e.getKey())))
.collect(Collectors.groupingBy(Pair::getStop,
Collectors.mapping(Pair::getBus, Collectors.toSet())));
}
当使用路线地图调用时,以下将是结果。
Station=[32, 13]
School=[13]
Brown Street=[32, 13]
High Street=[32, 13]
Acacia Avenue=[32]
Broadway=[32]
Hospital=[13]
为了使这个方法顺利运行,你应该将类型更改为它们的定义接口。所以 HashMap<String, ArrayList<Integer>>
应该声明为 Map<String, List<Integer>>
,等等。这不仅适用于这个练习,而且是 Java 中的标准做法。你可以随时将对象传递或赋值给其定义的接口,但不能反之(无需转换),因为该接口的不同实现可能存在。
这里是一个更加命令式的解决方案,这可能是 Java 8 之前的方法。结果是相同的,但是在涉及到地图和集合的情况下,内容的顺序可能会改变。它使用嵌套循环首先迭代键(公交车号),然后迭代值(站点)。关键在于检查站点是否存在。如果不存在,就使用一个新的 HashSet 将它添加进去。然后简单地跳出条件并将公交车号添加到集合中。
public Map<String, Set<Integer>> getStopsAndBusNumbers2(
Map<Integer, List<String>> map) {
Map<String, Set<Integer>> result = new HashMap<>();
for (Entry<Integer, List<String>> e : map.entrySet()) {
for (String stop : e.getValue()) {
if (!result.containsKey(stop)) {
result.put(stop, new HashSet<Integer>());
}
result.get(stop).add(e.getKey()); // add bus for stop
}
}
return result;
}
英文:
> I want to return a map derived from routes, in which each stop included in the routes map is a key and each value is a set of bus numbers that have that stop on their route.
I believe this will work do what you want.
- first allocate a record to hold a Stop and Bus number. The
Map.entry()
method could also be used but the record doesn't cost anything and gives the arguments meaningful names. - then stream the existing map's entrySet()
- Then using
flatMap()
, stream theentrySet's
stops. Each stop and the associated bus will then be mapped to the record. - Now it is just a matter of grouping each stop to a set of buses.
- Collectors.groupingBy will also take another collector, in this case Collectors.mapping to extract the Bus number from the
Pair
instance, and then put in a set.
record Pair(String getStop, Integer getBus) {}
public Map<String, Set<Integer>> getStopsAndBusNumbers(Map<Integer, List<String>> map) {
return map.entrySet()
.stream()
.flatMap(e->e.getValue().stream().map(stop->new Pair(stop, e.getKey())))
.collect(Collectors.groupingBy(Pair::getStop,
Collectors.mapping(Pair::getBus, Collectors.toSet())));
}
When called with the routes map, here will be the results.
Station=[32, 13]
School=[13]
Brown Street=[32, 13]
High Street=[32, 13]
Acacia Avenue=[32]
Broadway=[32]
Hospital=[13]
For this to work smoothly, you should change your types to their defining interface.
So HashMap<String, ArrayList<Integer>>
should be declared as Map<String, List<Integer>>
, etc. This is not just for this exercise but is standard practice in Java. You can always pass or assign an object
to its defining interface
but not the converse (without casting) since different implementations of that interface could exist.
Here is a more imperative solution that might have been the approach prior to Java 8. The results are the same although when maps and sets are involved the order of contents may change. It uses a nested loop to first iterate over the keys (buses) and then the values (stops). The heart of the matter is to check if the stop exists. If not, add it with a new HashSet. Then simply continue out of the conditional and add the bus number to the set.
public Map<String, Set<Integer>> getStopsAndBusNumbers2(
Map<Integer, List<String>> map) {
Map<String, Set<Integer>> result = new HashMap<>();
for (Entry<Integer, List<String>> e : map.entrySet()) {
for (String stop : e.getValue()) {
if (!result.containsKey(stop)) {
result.put(stop, new HashSet<Integer>());
}
result.get(stop).add(e.getKey()); // add bus for stop
}
}
return result;
}
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论