如何通过Java

时间:2018-10-03 16:54:10

标签: java csv filtering java.util.scanner

因此,我正在使用扫描仪从文件中读取具有类似格式的文件:

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”,尽管这是一个繁重的学习过程。

3 个答案:

答案 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的概念,但这可能会或可能不会成为问题,具体取决于您的要求。