Как указать свойство класса из строки в Java - PullRequest
0 голосов
/ 03 октября 2018

Итак, я читаю из файла со сканером, он имеет похожий формат:

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

Когда мое консольное приложение запустится, я запрашиваю у них (пользователя) данные, которые им нужны.Таким образом, они могут ввести «возраст». Поэтому я заблудился, как взять эту «возрастную» строку и получить к ней доступ к объекту персонажа.Идеальным вариантом для вывода программы должно быть: 20,30,24 прохождение каждого периода и вывод на печать

Я беру их входные данные так, String input = scanner.nextLine(); Затем я перебираю свой массив объектов person, чтобы получить индекс входных данных.Когда у меня есть этот индекс, я хочу получить доступ к свойству человека в индексе.Например, если мой индекс равен 1, я бы хотел получить доступ к свойству name.

В javascript я мог бы взять строку и сказать person['age'], хотя java - это совсем другая история.Я изучил Java API "Reflection", хотя это сложная кривая обучения.

Ответы [ 3 ]

0 голосов
/ 03 октября 2018

Прежде всего, мы должны добавить конструктор к вашему 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);
0 голосов
/ 03 октября 2018

Хотя в целом я не одобряю использование 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, но это может или не может быть проблемой в зависимости от ваших требований.

0 голосов
/ 03 октября 2018

Я изучил Java-интерфейс «Reflection API», хотя это сложная кривая обучения.

Что ж, Reflection - это путь .Он широко используется во многих рамках.

Но, возможно, более простое решение подойдет вашим потребностям.Используйте 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);
      }
  }
}

Инкапсуляция переключателя внутри метода соответствует принципам ООП, поскольку он скрываеткак атрибуты хранятся от других объектов, только открывая интерфейс для их запроса.Отражение нарушает всю инкапсуляцию.

...