返回从 ArrayList 派生的哈希映射。

huangapple go评论140阅读模式
英文:

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&lt;Integer,ArrayList&lt;String&gt;&gt; routes;

    public void populateRoutes()
    {
        ArrayList&lt;String&gt; stops = new ArrayList&lt;&gt;();
        stops.add(&quot;High Street&quot;);
        stops.add(&quot;Acacia Avenue&quot;);
        stops.add(&quot;Brown Street&quot;);
        stops.add(&quot;Broadway&quot;);
        stops.add(&quot;Station&quot;);
        routes.put(32, stops);

        ArrayList&lt;String&gt; stops1 = new ArrayList&lt;&gt;();
        stops1.add(&quot;High Street&quot;);
        stops1.add(&quot;Hospital&quot;);
        stops1.add(&quot;Brown Street&quot;);
        stops1.add(&quot;School&quot;);
        stops1.add(&quot;Station&quot;);
        routes.put(13, stops1);
    }

    public BusRoutes() {
        routes = new HashMap&lt;&gt;();
        reader = new InputReader();
        populateRoutes();        
    }
    public void printRoute(int busNum) {
        System.out.println(&quot;Bus number &quot; + busNum + &quot; route:&quot;);

        for (int i = 0; i &lt; routes.get(busNum).size(); i++) {
            System.out.println(routes.get(busNum).get(i));
        }        

    }

    public void printAllRoutes() {
        for (int i = 0; i &lt; routes.size(); i++) {
            System.out.println(routes.get(i));
        }       
    }

    public HashSet&lt;Integer&gt; getBusesStoppingHere(String aStop) {    
        HashSet&lt;Integer&gt; busNumbers = new HashSet&lt;&gt;();

        for (Integer key : routes.keySet()) {
            if (routes.get(key).contains(aStop)) {
                busNumbers.add(key);
            }
        }

        return busNumbers;
    }

    public HashMap&lt;String, HashSet&lt;Integer&gt;&gt; getStopsAndBusNumbers() {
        HashMap&lt;String, HashSet&lt;Integer&gt;&gt; map = new HashMap&lt;String, HashSet&lt;Integer&gt;&gt;();
        
        // 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 the entrySet&#39;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&lt;String, Set&lt;Integer&gt;&gt; getStopsAndBusNumbers(Map&lt;Integer, List&lt;String&gt;&gt; map) {
  return map.entrySet()
      .stream()
      .flatMap(e-&gt;e.getValue().stream().map(stop-&gt;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&lt;String, ArrayList&lt;Integer&gt;&gt; should be declared as Map&lt;String, List&lt;Integer&gt;&gt;, 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&lt;String, Set&lt;Integer&gt;&gt; getStopsAndBusNumbers2(
        Map&lt;Integer, List&lt;String&gt;&gt; map) {
    Map&lt;String, Set&lt;Integer&gt;&gt; result = new HashMap&lt;&gt;();
    for (Entry&lt;Integer, List&lt;String&gt;&gt; e : map.entrySet()) {
        for (String stop : e.getValue()) {
            if (!result.containsKey(stop)) {
                result.put(stop, new HashSet&lt;Integer&gt;());
            }
            result.get(stop).add(e.getKey()); // add bus for stop
        }
    }
    return result;
}
 


</details>



huangapple
  • 本文由 发表于 2023年3月10日 01:32:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/75688122.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定