如何在java中从字符串指定类属性
所以我用扫描仪读取一个文件,它的格式类似:如何在java中从字符串指定类属性,java,csv,filtering,java.util.scanner,Java,Csv,Filtering,Java.util.scanner,所以我用扫描仪读取一个文件,它的格式类似: title, name, age Mr, Matthew, 20 mr, Paul, 30 miss, Anne, 24 CSV^ 控制台程序 Scanner input = new Scanner(System.in); System.out.println("Please select what data you want to load:"); String selection = input.next();
title, name, age
Mr, Matthew, 20
mr, Paul, 30
miss, Anne, 24
CSV^
控制台程序
Scanner input = new Scanner(System.in);
System.out.println("Please select what data you want to load:");
String selection = input.next();
int temp = 0;
for(int i=0; i< header.length; i++){
if(header[i].equals(selection)){
temp = i;
break;
}
}
扫描仪输入=新扫描仪(System.in);
System.out.println(“请选择要加载的数据:”);
字符串选择=input.next();
内部温度=0;
对于(int i=0;i
temp将为我们提供指定选项的索引,因此如果是2,我们将希望访问age属性
当我的控制台应用程序运行时,我会提示他们(用户)输入他们想要的数据。
所以他们可能会输入“age”,所以我不知道如何获取这个“age”字符串并使用它访问person对象。
程序输出的理想情况应该是:20,30,24
遍历各个年龄段并打印
我接受他们的输入,所以String input=scanner.nextLine()代码>
然后,我循环遍历person对象数组以获取输入的索引。一旦我有了这个索引,我就想在索引处访问person的属性。所以,如果我的索引是1,我想访问属性“name”
在javascript中,我可以用字符串说person['age']
,尽管java是一个完全不同的故事。我研究了java的“反射API”,尽管这是一个繁重的学习过程
我研究了java的“反射API”,尽管这是一个繁重的学习过程
嗯,反思才是出路。它广泛应用于许多框架中
但也许一个更简单的解决方案会满足您的需要。使用开关
决定返回哪个属性,并将其封装在Person
类的方法中:
class Person {
private String name, title;
private int age;
public loadData(String csv){
String[] list = csv.split(",");
name = list[0];
title = list[1];
age = Integer.parseInt(list[2]);
}
public Object attribute(String attribute) {
switch (attribute) {
case "name": return this.name;
case "title": return this.title;
case "age": return this.age;
default: throw new RuntimeException("Invalid attribute: " + attribute);
}
}
}
public class Person {
Map<String, String> props = new HashMap<>();
public void addProperty(String propertyName, String value) {
// could add error checking to ensure propertyName not null/emtpy
props.put(propertyName, value);
}
/**
* returns the value of the property; may return null
*/
public String getProperty(String propertyName) {
return props.get(propertyName);
}
}
将开关封装在方法中符合OOP原则,因为它隐藏了其他对象的属性存储方式,只公开了查询属性的接口。反射破坏了所有的封装。首先,我们应该为您的Person
类添加一个构造函数
class Person {
public Person(String name, String title, int age) {
this.name = name;
this.title = title;
this.age = age;
}
}
现在,当您阅读输入时,您可以使用映射
,如下所示。在这里,在阅读每一行之后,我们创建一个Person
对象,然后使用该人的年龄在地图中创建一个条目,其中键为age
,值为Person
Map<Integer, Person> mapOfPeople = new HashMap<>();
while (input.hasNextLine()) {
String line[] = input.nextLine().split(",");
Perso person = new Perso(line[1], line[0], Integer.parseInt(line[2].trim()));
mapOfPeople.put(person.getAge(), person);
}
虽然通常我不赞成使用Map
来保存对象的字段,但如果属性的数量很大,甚至可能在CSV文件中有所不同(例如,一些文件中有一个人上过大学,另一个没有),那么使用Map
来保存属性可能是合适的
在这种情况下,可以定义一个简单的Person
类:
class Person {
private String name, title;
private int age;
public loadData(String csv){
String[] list = csv.split(",");
name = list[0];
title = list[1];
age = Integer.parseInt(list[2]);
}
public Object attribute(String attribute) {
switch (attribute) {
case "name": return this.name;
case "title": return this.title;
case "age": return this.age;
default: throw new RuntimeException("Invalid attribute: " + attribute);
}
}
}
public class Person {
Map<String, String> props = new HashMap<>();
public void addProperty(String propertyName, String value) {
// could add error checking to ensure propertyName not null/emtpy
props.put(propertyName, value);
}
/**
* returns the value of the property; may return null
*/
public String getProperty(String propertyName) {
return props.get(propertyName);
}
}
尽管注意,对于大多数数据集,我希望名称不是单个条目,因为通常会有姓、名等。尽管如此,有限数量的常见期望值的模式是相同的。此外,还可以进行调整,以便可以直接获得某些已知字段的整数值
然后,在解析文件时,保留包含属性定义的标题行。然后,对于随后读取的每一行,创建一个新的Person
对象,然后按顺序添加属性
List<Person> allPersons = new ArrayList<>();
while ( (line = READ_NEXT_LINE) ) {
// NOTE: this is not a safe way to handle CSV files; should really
// use a CSV reader as fields could have embedded commas
attrs[] = line.split(",");
Person p = new Person();
for (int i = 0; i < titleRow.length; ++i) {
p.addProperty(titleRow[i], attrs[i]);
}
allPersons.add(p);
}
请注意,这种方法确实打破了Javabean
的概念,但这可能是一个问题,也可能不是一个问题,这取决于您的需求。“当我的控制台应用程序运行时,我会提示他们(用户)输入他们想要的数据”--请也共享该代码。@NicholasK doneSo您只想按年龄
搜索吗?没错@尼古拉斯反射实际上是最糟糕的选择,应该尽量避免。它很慢,因为JIT编译器无法优化它;它很容易出错,因为在编译时无法检测到错误。这是一个很有帮助的答案,尽管在我的实际程序(不是上面的程序)中,我有20个或更多的属性,并且正在尝试避免为硬编码的可能性做准备,因为它不是很有效。学习API的效率较低,你自己说的API有一个陡峭的学习曲线。。。不是吗?如果数据集包含超过1个给定年龄的人,会发生什么情况?此外,我知道OP只对年龄搜索感兴趣,但正如OP在对另一个问题的评论中所指出的那样,如果存在许多属性,那么长期方法似乎不太可能只依赖一个年龄属性进行搜索。因此,这个示例代码不会缩放。嗯,是的,缩放不是这里的问题。我确实理解两个人年龄相同的问题,但我想把这个问题转到@Matthew Fallon。在这种情况下会发生什么?
List<Person> allPersons = new ArrayList<>();
while ( (line = READ_NEXT_LINE) ) {
// NOTE: this is not a safe way to handle CSV files; should really
// use a CSV reader as fields could have embedded commas
attrs[] = line.split(",");
Person p = new Person();
for (int i = 0; i < titleRow.length; ++i) {
p.addProperty(titleRow[i], attrs[i]);
}
allPersons.add(p);
}
// find all people of a given age
List<Person> peopleAge20 = allPersons.stream()
.filter(p -> p.getAge() == 20)
.collect(Collectors.toList());
System.out.println(peopleAge20);
// summary statics (average age) for all people
IntSummaryStatistics stats =
allPersons.stream().mapToInt(p -> p.getAge()).summaryStatistics();
System.out.printf("Average age: %f\n", stats.getAverage());