Возможно ли создать список из нескольких объектов, где объекты принимают несколько аргументов?

#java #for-loop #arraylist #collections #jvm

#java #for-цикл #arraylist #Коллекции #jvm

Вопрос:

Упрощенный пример

Представьте, что я определяю person как:

 public class Person (String name, int age)
  

и тогда у меня есть список людей…

 public class ListOfPeople {
     private ArrayList<Person> people;
}
  

затем я хочу иметь возможность создавать несколько человек за один раз, делать что-то вроде…

 ListOfPeople myFriends = new ListOfPeople("Chris",33,"Adam",26,"John",50)
  

Я знаю, что мог бы инициализировать каждый из них по отдельности, а затем добавить их, мне просто было любопытно посмотреть, могу ли я каким-то образом просто создать их «на лету», как описано выше

Комментарии:

1. Каков источник для набора имен и возрастов?

2. Что-то не так с выполнением new ListOfPeople(new Person("Chris", 33), new Person("Adam", 26), new Person("John", 50)) ? Тогда вы не добавляете их после их создания, и это все еще работает на лету. Если это не сработает, вы всегда можете создать для себя пользовательский ArrayList класс, который наследует basic ArrayList и имеет пользовательский конструктор, который принимает строки и инициализирует все, чтобы вы могли передавать данные, как в вашем примере.

3. Вы также могли бы черпать вдохновение из java 9 java.util.Map.of(K, V, K, V, ...)

4. Просто для записи: список людей, который вы решаете, создавая простой List<People> объект. Если ваш класс содержит только этот внутренний список… тогда это не добавляет никакой ценности вашему дизайну. У Java уже есть коллекции. Ваш новый класс только усложняет задачу, например, вам придется реализовать equals() , hashCode() и toString(), чтобы сделать что-то полезное. Итак, имхо, первое, что нужно сделать: спросите себя, действительно ли вам нужен или нужен этот специальный класс ListOfSomething . Или наоборот: как вы думаете, вы хотите создать такой новый класс для каждого и любого

5. @GhostCat в реальной жизни сценарий более сложный и требует большего, чем просто простой список, я просто убирал его для краткости и простоты понимания

Ответ №1:

Вы могли бы сделать что-то вроде этого:

 List<Person> personListConstructor(String... data) {
    List<Person> personList = new ArrayList<>();
    for (int i = 0; i < data.length / 2; i  ) {
        personList.add(new Person(data[2 * i], Integer.parseInt(data[2 * i   1])));
    }
    return personList;
}
  

Конечно, ему не хватает проверки — должно быть четное количество аргументов, каждая секунда должна быть целым числом. Другим решением было бы использовать массив Object s:

 List<Person> personListConstructor(Object... data) {
    List<Person> personList = new ArrayList<>();
    for (int i = 0; i < data.length / 2; i  ) {
        personList.add(new Person((String) data[2 * i], (Integer) data[2 * i   1]));
    }
    return personList;
}
  

Те же уведомления здесь.

Комментарии:

1. Может быть, не самый элегантный, но он, безусловно, подходит для моего требования!

Ответ №2:

Вы можете создать конструктор, который принимает массив Person объектов:

 public class ListOfPeople {
     private ArrayList<Person> people;

     public ListOfPeople(Person... persons) {
          for (Person person : persons) {
               people.add(person);
          }
     }
}
  

И используйте его следующим образом:

 ListOfPeople myFriends = new ListOfPeople(new Person("Chris", 33), new Person("Adam",26), new Person("John",50));
  

Ответ №3:

Было интересно, как это сделать, используя lambda, и вот простое решение, если кому-то интересно.

 public class Person {
    String name;
    int age;

    public Person(List<String> attributes) {
        attributes.stream().findFirst().ifPresent(this::setName);
        attributes.stream().skip(1).findFirst().map(Integer::parseInt).ifPresent(this::setAge);
    }
    // getters, setters

}

public class ListOfPersons {
    List<Person> people;

    public ListOfPersons(String ...persons) {
        final int chunkSize = 2;
        final AtomicInteger counter = new AtomicInteger();

        this.people = Stream.of(persons)
            .collect(Collectors.groupingBy(it -> counter.getAndIncrement() / chunkSize))
            .values()
            .stream()
            .map(Person::new)
            .collect(Collectors.toList());
        System.out.println(Arrays.toString(this.people.toArray()));
    }
}
  

Итак, new new ListOfPersons("A", "1", "B", "2", "C") возвращает

 [Person{name='A', age=1}, Person{name='B', age=2}, Person{name='C', age=0}]
  

Комментарии:

1. Мне потребуется некоторое время, чтобы прочитать и понять, как это работает, но это выглядит очень впечатляюще! Я не знаком с потоками и понятия не имею, что такое AtomicInteger, но я проведу некоторое исследование 🙂