Java 返回与年份和等级关联的字符串

Java 返回与年份和等级关联的字符串,java,hashmap,set,maps,Java,Hashmap,Set,Maps,基本上我有一张这样的地图 HashMap<Integer, HashMap<String, Integer>> girls = new HashMap<Integer, HashMap<**String**, Integer>>();' 我不知道如何做上面的标题试试看 return girls.getOrDefault(year, Collections.emptyMap()).entrySet().stream() .

基本上我有一张这样的地图

HashMap<Integer, HashMap<String, Integer>> girls = 
new HashMap<Integer, HashMap<**String**, Integer>>();'
我不知道如何做上面的标题

试试看

return girls.getOrDefault(year, Collections.emptyMap()).entrySet().stream()
            .filter(e -> e.getValue() == rank)
            .map(e -> e.getKey())
            .findFirst()
            .orElse(null);

如果可以避免,请不要使用地图地图。有些原因和情况下,你可能想,但这是非常混乱,因为你已经看到自己

这不是你想要的情况之一。只需声明一个新类来封装此信息并将其存储在列表中:

class Girl
{
   // Declare getters if you want
   public final int    year;
   public final int    rank;
   public final String name;

   Girl(int year, int rank, String name){
       this.year = year;
       this.rank = rank;
       this.name = name;
   }
}
现在,您的数据结构并不是一团糟:

List<Girl> girls = new ArrayList<>();

您可以通过以下方式对地图进行流式处理:

//get the map that match the year:
Map<String, Integer> mapForKeyYear = g.getOrDefault(year, null);

//if the map is not null then filter that map to the rank:

String r = mapForKeyYear
        .entrySet().stream()
        .filter(e -> e.getValue() == rank)
        .map(Map.Entry::getKey)
        .findFirst().orElse(null);
//获取与年份匹配的地图:
Map mapForKeyYear=g.getOrDefault(年份,空);
//如果映射不为空,则将该映射过滤到秩:
字符串r=mapForKeyYear
.entrySet().stream()
.filter(e->e.getValue()==rank)
.map(map.Entry::getKey)
.findFirst().orElse(null);

如上所述,您的代码不会编译,原因超过您提到的原因

我认为你误解了如何使用地图。地图就像书中的词汇表一样使用。词汇表包含主题的页码。在类似意义上,映射包含给定(k[页码])的值(v[值])


但是你可以告诉电脑你想储存什么。因此,您需要了解键和值,以便正确构建映射。

让我们尝试直观地查看
HashMap
的结构,因为它是一个相当复杂的数据结构

//             A         B
//         |--------|--------|
//      C                              D
//  |------|---------------------------------------------------------------------|
{
    Integer: {String: Integer, String: Integer, String: Integer, String: Integer},
    Integer: {String: Integer, String: Integer, String: Integer, String: Integer},
    Integer: {String: Integer, String: Integer, String: Integer, String: Integer},
    Integer: {String: Integer, String: Integer, String: Integer, String: Integer}
}
部分A和C是键,B和D是值

现在让我们看看
.get(year).get(rank)是什么。首先,调用
get(year)
year
是C节中的一个值,因此
get(year)
在D节中返回一个值。接下来,调用
get(rank)
。由于它是在
get(year)
的返回值上调用的,
rank
在a部分中有一个值。
get(rank)
将在D部分中返回一个值,这些值都是
整数。因此,会发生编译器错误


要解决这个问题,只需在内部映射中交换这两种类型。您从
HashMap
更改为
HashMap

感觉您的内部映射应该从Integer->String,而不是String->Integer:
HashMap
。您正以相反的方式使用HashMap。您可以使用键来获取值,而不是使用值来获取键。将内部hashmap翻转为将整数映射为字符串将解决此问题。对于理解映射有困难的人来说,可能出现的重复将不会从包含lambdas和streams的解决方案中受益。播放给你的听众听。@Michael我在回答中没有看到集合的使用。emptyMap()无论如何感谢feedbak…你是对的,但是
集合。emptyMap()
是一个改进,因为你的可能会出现空指针异常。所以我错了,几乎一样,但更糟;)词汇表提供了单词的定义(这也是地图的类比…)。你在想一个索引。在你的类比中,你还混淆了键和值。人们会去索引中寻找一个单词(键),然后得到一个页码(值)。你的类比也不成立,因为可以有多个页面(值)与一个单词(键)关联。这在标准的一对一映射中是不可能的。根本问题是,正如您所说,它是“一个复杂的数据结构”。解决方案应该是降低数据结构的复杂性。@Michael,是的。你的回答中已经提到了这一点,所以我只是提供一个替代方案。这很好,但说得更清楚也无妨如果映射的不同
名称
(字符串
键)可以具有相同的
(整数
值)…@Spock(如果确实存在相同的秩),则无法应用您的解决方案。OP希望从
get(rank)
中获得什么?OP显然是想从一个等级中得到这个名字。
//get the map that match the year:
Map<String, Integer> mapForKeyYear = g.getOrDefault(year, null);

//if the map is not null then filter that map to the rank:

String r = mapForKeyYear
        .entrySet().stream()
        .filter(e -> e.getValue() == rank)
        .map(Map.Entry::getKey)
        .findFirst().orElse(null);
//             A         B
//         |--------|--------|
//      C                              D
//  |------|---------------------------------------------------------------------|
{
    Integer: {String: Integer, String: Integer, String: Integer, String: Integer},
    Integer: {String: Integer, String: Integer, String: Integer, String: Integer},
    Integer: {String: Integer, String: Integer, String: Integer, String: Integer},
    Integer: {String: Integer, String: Integer, String: Integer, String: Integer}
}