具有多个值的 HashMap get.key() 错误
HashMap with multiple values get.key() error
import java.util.*;
class Student{
final String name;
final String gender;
public String number;
static Map<String, ArrayList<String>> hm = new HashMap<String, ArrayList<String>>();
static ArrayList<String> nameandNumber = new ArrayList<>();
Student(String number, String name, String gender) {
this.name = name;
this.gender = gender;
this.number = number;
nameandNumber.add(this.name);
nameandNumber.add(this.number);
hm.put(this.gender,nameandNumber);
}
void getPersonByGender() {
String[] Liste = hm.get("Man").toArray(new String[0]);
for (int i = 0; i < Liste.length - 1; i += 2) {
System.out.println(Liste[i] + "\t<------>\t" + Liste[i + 1]);
}
}
}
大家好,我正在创建一个class,这个class会return给我10个学生信息,我会给出(根据男女差异)。当我尝试使用 getPersonByGender 的函数时,此函数会为我提供所有学生。
static ArrayList<String> nameandNumber = new ArrayList<>();
new
很有用:计算代码调用的次数 new ArrayList
。这是一个相当简单的答案:一次。对于您的整个程序。
如果你只调用一次new
,那意味着只有一个列表。在整个系统中。
难怪:这个:
nameandNumber.add(this.number);
您的应用程序的单个 'run' 被调用 10 次(因为有 10 个学生)。因此,您拥有的那个列表必须因此将所有这些数字加在一起 - 这就是为什么您会看到所有数据。
不幸的是,您的代码包含多层糟糕的设计决策。
您可以 'fix' 解决问题(但它仍然是难以阅读的脆弱代码),或者您可以 'fix' 设计(这需要更多工作)。
解决问题
您想要为每个学生调用 new ArrayList
,而不是所有学生共享的 1 个列表,这显然是行不通的。摆脱那个 static
单个数组列表,而是每次都创建一个:
Student(String number, String name, String gender) {
this.name = name;
this.gender = gender;
this.number = number;
var nameandNumber = new ArrayList<String>();
nameandNumber.add(this.name);
nameandNumber.add(this.number);
hm.put(this.gender, nameandNumber);
}
例如,现在您在一个 运行 程序中调用 new ArrayList
的正确次数。
但是您在这里仍然遇到麻烦 - 因为您决定使用 List
来表示单个想法(学生),所以您自己感到困惑:给定的性别映射到 多名 名学生。鉴于单个学生由 List<String>
表示,多个学生将由 List<List<String>>
表示,哦,这变得非常复杂,非常快。
我们可以插手进一步解决这个问题,但让我们退后一步,改为修复您的设计!
修改设计
更一般地说,java 的类型系统是高度名义化的:类型有名称,名称越具有描述性越好。
Student
是一个比 List<String>
更好、更清晰的名字 。您的代码的 reader 应该如何知道那些 List<String>
对象专门用于恰好包含 2 个字符串,第一个是学生的姓名,第二个是他们的学号?它没有在任何地方这么说。如果你搞砸了,你不会得到任何类型的编译器错误。
你有一个类型,就在那里,正确描述了这个概念:Student
!
那么为什么不替换这个错误的代码:
static Map<String, ArrayList<List<String>>> hm = new HashMap<String, ArrayList<List<String>>>();
有了这个大大改进的代码:
static Map<String, List<Student>> genderMap = new HashMap<>();
它有各种改进:
- 它有一个专有名称。
hm
没有任何意义。
- 它使用
<>
来缩短 - 你不需要重复那些东西。
- 它编码为原理(
List
)而不是具体的class。
- 它使用名义类型 - 这将性别字符串映射到学生列表。而且代码读起来一样,很好。
放在一起:
class Student {
final String name;
final String gender;
final String number;
static Map<String, List<Student>> genderMap = new HashMap<>();
Student(String number, String name, String gender) {
this.name = name;
this.gender = gender;
this.number = number;
List<Student> studentsForThisGender = genderMap.get(gender);
if (studentsForThisGender == null) {
// There is no list yet; we need to make one.
genderMap.put(gender, studentsForThisGender = new ArrayList<>());
}
studentsForThisGender.add(this);
}
static void getPersonByGender() {
Student[] liste = genderMap.get("Man").toArray(new Student[0]);
for (Student student : liste) {
System.out.println(student.name + "\t<------>\t" + student.number);
}
}
}
注:
- getPersonByGender 现在是
static
- 这是您对 'students' 而不是任何特定学生的概念所做的事情。
- 我们打印
student.name
文件本身,而不是这个模糊的“打印列表[0] - 你只需要知道那是名字”。
- 我们解决了您所在的问题 list-confused。
- 如果您在 java 研究中取得更进一步的进展,那么 'get the list of students for a given gender, and make a new list if neccessary' 可以更简洁。最后 4 行可以简化为:
genderMap.computeIfAbsent(gender, () -> new ArrayList<>()).add(this);
但我敢打赌,您的 java 课程中还没有涵盖语法以及那里发生的事情。
import java.util.*;
class Student{
final String name;
final String gender;
public String number;
static Map<String, ArrayList<String>> hm = new HashMap<String, ArrayList<String>>();
static ArrayList<String> nameandNumber = new ArrayList<>();
Student(String number, String name, String gender) {
this.name = name;
this.gender = gender;
this.number = number;
nameandNumber.add(this.name);
nameandNumber.add(this.number);
hm.put(this.gender,nameandNumber);
}
void getPersonByGender() {
String[] Liste = hm.get("Man").toArray(new String[0]);
for (int i = 0; i < Liste.length - 1; i += 2) {
System.out.println(Liste[i] + "\t<------>\t" + Liste[i + 1]);
}
}
}
大家好,我正在创建一个class,这个class会return给我10个学生信息,我会给出(根据男女差异)。当我尝试使用 getPersonByGender 的函数时,此函数会为我提供所有学生。
static ArrayList<String> nameandNumber = new ArrayList<>();
new
很有用:计算代码调用的次数 new ArrayList
。这是一个相当简单的答案:一次。对于您的整个程序。
如果你只调用一次new
,那意味着只有一个列表。在整个系统中。
难怪:这个:
nameandNumber.add(this.number);
您的应用程序的单个 'run' 被调用 10 次(因为有 10 个学生)。因此,您拥有的那个列表必须因此将所有这些数字加在一起 - 这就是为什么您会看到所有数据。
不幸的是,您的代码包含多层糟糕的设计决策。
您可以 'fix' 解决问题(但它仍然是难以阅读的脆弱代码),或者您可以 'fix' 设计(这需要更多工作)。
解决问题
您想要为每个学生调用 new ArrayList
,而不是所有学生共享的 1 个列表,这显然是行不通的。摆脱那个 static
单个数组列表,而是每次都创建一个:
Student(String number, String name, String gender) {
this.name = name;
this.gender = gender;
this.number = number;
var nameandNumber = new ArrayList<String>();
nameandNumber.add(this.name);
nameandNumber.add(this.number);
hm.put(this.gender, nameandNumber);
}
例如,现在您在一个 运行 程序中调用 new ArrayList
的正确次数。
但是您在这里仍然遇到麻烦 - 因为您决定使用 List
来表示单个想法(学生),所以您自己感到困惑:给定的性别映射到 多名 名学生。鉴于单个学生由 List<String>
表示,多个学生将由 List<List<String>>
表示,哦,这变得非常复杂,非常快。
我们可以插手进一步解决这个问题,但让我们退后一步,改为修复您的设计!
修改设计
更一般地说,java 的类型系统是高度名义化的:类型有名称,名称越具有描述性越好。
Student
是一个比 List<String>
更好、更清晰的名字 。您的代码的 reader 应该如何知道那些 List<String>
对象专门用于恰好包含 2 个字符串,第一个是学生的姓名,第二个是他们的学号?它没有在任何地方这么说。如果你搞砸了,你不会得到任何类型的编译器错误。
你有一个类型,就在那里,正确描述了这个概念:Student
!
那么为什么不替换这个错误的代码:
static Map<String, ArrayList<List<String>>> hm = new HashMap<String, ArrayList<List<String>>>();
有了这个大大改进的代码:
static Map<String, List<Student>> genderMap = new HashMap<>();
它有各种改进:
- 它有一个专有名称。
hm
没有任何意义。 - 它使用
<>
来缩短 - 你不需要重复那些东西。 - 它编码为原理(
List
)而不是具体的class。 - 它使用名义类型 - 这将性别字符串映射到学生列表。而且代码读起来一样,很好。
放在一起:
class Student {
final String name;
final String gender;
final String number;
static Map<String, List<Student>> genderMap = new HashMap<>();
Student(String number, String name, String gender) {
this.name = name;
this.gender = gender;
this.number = number;
List<Student> studentsForThisGender = genderMap.get(gender);
if (studentsForThisGender == null) {
// There is no list yet; we need to make one.
genderMap.put(gender, studentsForThisGender = new ArrayList<>());
}
studentsForThisGender.add(this);
}
static void getPersonByGender() {
Student[] liste = genderMap.get("Man").toArray(new Student[0]);
for (Student student : liste) {
System.out.println(student.name + "\t<------>\t" + student.number);
}
}
}
注:
- getPersonByGender 现在是
static
- 这是您对 'students' 而不是任何特定学生的概念所做的事情。 - 我们打印
student.name
文件本身,而不是这个模糊的“打印列表[0] - 你只需要知道那是名字”。 - 我们解决了您所在的问题 list-confused。
- 如果您在 java 研究中取得更进一步的进展,那么 'get the list of students for a given gender, and make a new list if neccessary' 可以更简洁。最后 4 行可以简化为:
genderMap.computeIfAbsent(gender, () -> new ArrayList<>()).add(this);
但我敢打赌,您的 java 课程中还没有涵盖语法以及那里发生的事情。