Итерация по двум спискам только с одним итератором Java - PullRequest
2 голосов
/ 01 марта 2012

У меня есть некоторые проблемы, у меня есть два класса, и каждый возвращает Итератор, есть класс, который возвращает значения с именем Student. С помощью этого кода я могу перебирать один класс, и я хотел бы знать, есть ли способ перебрать другой класс, не добавляя второго, пока в моем классе Machine. Вот как выглядит мой код:

import java.util.*;
import java.lang.reflect.*;

class ClassRoom1{
    ArrayList<Student> al = new ArrayList<Student>();
    Student st; 
    public ClassRoom1(){
        st = new Student("Michael", "Smith", 12);
        al.add(st);
        st = new Student("Jennifer", "Lopez", 13);
        al.add(st);
    }

    public void addStudent(String name, String lastName, int age) {
        Student st = new Student(name, lastName, age);
        al.add(st);
    }

    public ArrayList getStudents(){
        return al;
    }

    public Iterator returnIter(){
        Iterator iter = getStudents().iterator();
        return iter;
    }
}

class ClassRoom2{
    ArrayList<Student> al = new ArrayList<Student>();
    Student st; 
    public ClassRoom2(){
        st = new Student("Brian", "Con", 15);
        al.add(st);
        st = new Student("Megan", "Bell", 15);
        al.add(st);
    }

    public void addStudent(String name, String lastName, int age) {
        Student st = new Student(name, lastName, age);
        al.add(st);
    }

    public ArrayList getStudents(){
        return al;
    }

    public Iterator returnIter(){
        Iterator iter = getStudents().iterator();
        return iter;
    }
}

public class Machine{
    Student st;
    ClassRoom1 clrm1 = new ClassRoom1();
    ClassRoom2 clrm2 = new ClassRoom2();    

    public static void main(String[] args){
        Machine mch = new Machine();
        ArrayList al = new ArrayList();
        Iterator iter = al.iterator();
        mch.printStudens(iter);
    }

    void printStudens(Iterator iter){
        iter = clrm1.returnIter();
        while(iter.hasNext()){
            st = (Student) iter.next();
            System.out.println("\nName: " + st.getName() + "\nLast name: " + st.getLastName() + "\nAge: " + st.getAge());
        }
    }
}

Ответы [ 5 ]

4 голосов
/ 01 марта 2012

Прежде всего, вместо дублирования кода используйте OO:

class ClassRoom{
    private List<Student> al;
    public ClassRoom1(List<Student> studentList){
        a1 = new ArrayList(studentList);
    }

    public void addStudent(String name, String lastName, int age) {
        al.add(new Student(name, lastName, age));
    }

    public List<Student> getStudents(){
        return al;
    }

    public Iterator<Student> returnIter(){
        return getStudents().iterator();
    }
}

Тогда clrm1 и clrm2 являются объектами ClassRoom.На самом деле вы можете хранить произвольное множество объектов ClassRoom в собственном списке и выполнять вложенные итерации, в первую очередь по всем классам, в которых вы перебираете всех студентов в текущем ClassRoom.


Обновление:

Если вам когда-то понадобится объединить итераторы (в этом нет необходимости), я либо напишу свой собственный маленький объединяющий итератор, который, например, последовательно, итерирует по содержащимся в нем итераторам, либо воспользуется Iterator.concat(), который использует GuavaMsgstr "Объединяет несколько итераторов в один итератор".В любом случае вам не придется дублировать какие-либо данные.

0 голосов
/ 01 марта 2012

Я не вижу причин для разных классов в двух классах: они одинаковые.

public class Classroom {
  // each classroom has a list of students
  List<Student> students = new ArrayList<Student>();

  // each classroom has a method to add a new student
  public void addStudent(String name, String lastName, int age) {
    Student st = new Student(name, lastName, age);
    al.add(st);
  }

  // each classroom has a method to "show" his students
  public List<Student> getStudents() {
    return students;
  }
}

Теперь у вас есть машина :

public class Machine{

    // a list of classrooms
    List<Classroom> classRooms = new ArrayList<Classroom>();

    // just to start the application
    public static void main(String[] args){
        Machine machine = new Machine();
        machine.printStudents();
    }

    public Machine() {
      // we initialize the classrooms
      // Note - a machine wouldn't create classes, this is just for the demo
      Classroom class1 = new Classroom();
      class1.addStudent("Michael", "Smith", 12);
      class1.addStudent("Jennifer", "Lopez", 13);
      classRooms.add(class1);

      Classroom class2 = new Classroom();
      class2.addStudent("Brian", "Con", 15);
      class2.addStudent("Brian", "Con", 15);          
      classRooms.add(class2);
    }

    void printStudents() {
      for (Classroom class:classrooms) {
        // one could print the classname at this place
        for (Student student: class.getStudents()) {
          System.out.println("\nName: " + st.getName() + "\nLast name: " + st.getLastName() + "\nAge: " + st.getAge());
        }
      }
    }
}

Это очень отличается от вашего решения - только один класс для классов и никаких итераторовони не нужны).Попробуйте и сравните с вашим кодом.

0 голосов
/ 01 марта 2012

Я согласен с ответами о плохом дизайне, но чтобы ответить на реальный вопрос, получите по одному итератору для обоих списков, код ниже должен работать. Это будет дорого с вычислительной точки зрения из-за копирования массива, так что вы можете использовать связанный список для смягчения этого.

clrm1.getStudents().clone().addAll(clrm2.getStudents()).iterator();

Другой вариант - использовать список объекта Class со списком студентов, а затем итератор сглаживания .

0 голосов
/ 01 марта 2012

Ваш дизайн совершенно неверный.Вы не должны создавать два разных (Java) класса для каждого (школьного) ClassRoom.Просто создайте один:

public class ClassRoom
{
    ... all your stuff here

    public void addStudent(Student st)
    {
        students.add(st);
    }

    public List<Student> getStudents()
    {
        return students;
    }
}

Затем вы можете создать несколько таких классов и поместить их в массив:

List<ClassRoom> rooms = new ArrayList<ClassRoom>();

ClassRoom room1 = new ClassRoom("5 Latin Sience");
room1.addStudent(new Student("Anna", "Bell", 12));
room1.addStudent(new Student("Martin", "Foo", 12));
room1.addStudent(new Student("Stef", "Bar", 12));


ClassRoom room2 = new ClassRoom("4 Maths");
room2.addStudent(new Student("Anna", "Bell", 11));
room2.addStudent(new Student("Martin", "Foo", 11));
room2.addStudent(new Student("Stef", "Bar", 15));

// put them int the array.
rooms.add(room1);
rooms.add(room2);

Теперь вы можете перебирать каждую классную комнату, а затем перебиратькаждый студент с вложенным циклом:

for (ClassRoom room : rooms)
{
    for (Student st : room.getStudents())
    {
        System.out.println(... student details here ...);
    }
}
0 голосов
/ 01 марта 2012

Я бы не назвал переменную с именем, похожим на ее тип (который может измениться), но с тем, что он будет содержать:

ArrayList<Student> students = new ArrayList<Student>();

Я бы изменил метод addStudent для принятияStudent, а не имя, фамилия и возраст.

  public void addStudent(Student newStudent) 
  {
          students.add(newStudent);
  }

Затем вы можете добавить ученика, например:

class1.addStudent(new Student("jennifer", "lopez", 30));

Но также можете добавить одного и того же ученика в разные классы:

Student jennifer = new Student("jennifer", "lopez", 30);
class1.addStudent(jennifer);
class2.addStudent(jennifer);

Наконец, да, вынужны два итератора в цикле:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...