因此,我正在使用扫描仪从文件中读取具有类似格式的文件:
title, name, age
Mr, Matthew, 20
mr, Paul, 30
miss, Anne, 24
CSV ^
class person{
String name, title;
int age;
public crimeData(String csv){
String[]list = csv.split(",", -1);
name = list[0];
title = list[1];
age = list[2];
}
}
控制台程序
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;
}
}
temp将为我们提供指定选项的索引,因此如果为2,我们将要访问age属性
当我的控制台应用程序运行时,我提示他们(用户)他们想要的数据。
因此他们可能会输入“ age”,因此我迷失了如何获取此“ age”字符串并使用其访问person对象的方法。
程序输出的理想情况应该是:20,30,24
经历各个时代并进行印刷
我接受了他们的意见,所以String input = scanner.nextLine();
然后,我遍历我的人员对象数组以获取输入的索引。一旦有了该索引,我便想访问该索引处person的属性。因此,就像我的索引为1一样,我想访问属性“名称”。
在Java语言中,我可以接受字符串并说person['age']
,尽管Java是另一回事。我已经研究了Java的“反射API”,尽管这是一个繁重的学习过程。
答案 0 :(得分:1)
我已经研究了Java的“反射API”,尽管这是一个繁重的学习工作。
好吧,反思是要走的路。它已在许多框架中广泛使用。
但是也许更简单的解决方案将满足您的需求。使用switch
决定要返回哪个属性,并将其封装在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);
}
}
}
将开关封装在该方法内部符合OOP原则,因为它隐藏了如何存储其他对象的属性,只公开了一个查询它们的接口。反射破坏了所有封装。
答案 1 :(得分:0)
首先,我们应该向您的Person
类添加一个构造函数。
class Person {
public Person(String name, String title, int age) {
this.name = name;
this.title = title;
this.age = age;
}
}
现在,当您阅读输入内容时,可以按以下方式使用Map
。在阅读完每一行之后,我们在这里创建了一个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);
}
现在要通过Person
来获取特定的age
,只需
mapOfPeople.get(20);
答案 2 :(得分:0)
尽管通常我不赞成使用Map
来保存对象的字段,但是如果属性的数量很大并且甚至可能在CSV文件中有所不同(例如,某个文件中有一个大学,参加,其他人则不需要),然后使用Map
来保存属性是合适的。
在这种情况下,将定义一个简单的Person
类:
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);
}
}
如果知道某些属性将始终被加载,则可以添加诸如getName()
之类的访问器:
public String getName() {
return props.get("name");
}
public int getAge() {
String age = props.get("age");
// or throw exception if missing
return (age != null ? Integer.parseInt(age) : -1);
}
尽管请注意,对于大多数数据集,我希望名称不会是一个条目,因为通常会有姓氏,名字等。尽管如此,有限数量的通常期望值的模式是相同的。此外,您可以进行调整,以便直接为某些知名字段获取整数值。
然后,当您解析文件时,保留具有属性定义的标题行。然后,为随后读取的每一行创建一个新的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);
}
然后您可以通过Person
获得特定的Person myPerson = allPersons.get(index_of_person)
,并且与使用Javascript
的方式非常相似,可以执行String val = myPerson.getProperty("age")
。
如果您需要按给定的属性进行搜索,则可以在allPersons
上进行流式处理/循环,并根据给定的属性检查等效性。
// 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());
请注意,这种方法确实破坏了Javabean
的概念,但这可能会或可能不会成为问题,具体取决于您的要求。