如何找出抽象列表中的对象?

时间:2019-07-19 05:13:31

标签: java list loops class arraylist

我有一个称为会话的抽象类。讲座和教程扩展了会议。然后,我有一个称为注册的类,其中包含一个会话列表(讲座和教程)。如何在“注册”中的会话列表中循环浏览,并仅从会话列表中返回讲座列表?

我的下一个问题是,我是否应该存储2个列表。一个讲座列表和一个教程列表,而不是一个会话列表?这是因为会话列表对我来说毫无用处,我每次都必须遍历该列表以获取有关讲座和教程的信息。有没有一种我无法获得所有讲座对象的方法?我是Java新手。

public class Enrolment {

    private List<Session> sessions;

    public Enrolment() {
        this.sessions = new ArrayList<>();
    }

    public addSession(Session session) {
        this.sessions.add(session);
    }
}

public class Session {

    private int time;

    public Session(int time) {
        this.time = time;
    }
}

public class Lecture extends Session {

    private String lecturer;

    public Lecture(int time, String lecturer) {
        super(time);
        this.lecturer = lecturer;
    }
}

public class Tutorial extends Session {

    private String tutor;
    private int tutorScore;

    public Tutorial(int time, String tutor, int tutorScore) {
        super(time);
        this.tutor = tutor;
        this.tutorScore = tutorScore;
    }

}

public class test {
    public static void main(String[] args) {
        Enrolment newEnrolment = new Enrolment();

        Lecture morningLec = new Lecture(900, "Dr. Mike");
        newEnrolment.addSession(morningLec);

        Tutorial afternoonTut = new Tutorial(1400, "John Smith", 3);
        newEnrolment.addSession(afternoonTut);

        Lecture middayLec = new Lecture(1200, "Mr. Micheals");
        newEnrolment.addSession(middayLec);

        Tutorial NightTut = new Tutorial(1900, "Harry Pauls", 4);
        newEnrolment.addSession(NightTut);
    }
}

6 个答案:

答案 0 :(得分:4)

流式传输sessions列表并使用instanceof过滤Lectures类型的对象

List<Lecture> l = sessions.stream()
                           .filter(Lecture.class::isInstance) 
                           .map(Lecture.class::cast)                               
                           .collect(Collectors.toList());

通过使用for循环为每种类型使用两个不同的列表

List<Lecture> l = new ArrayList<>();
List<Tutorial> t = new ArrayList<>();
for (Session s : sessions) {
    if (s instanceof Lecture) {
        l.add((Lecture) s);
    }
      else if(s instanceof Tutorial) {
        t.add((Tutorial) s);
    }
}

答案 1 :(得分:2)

  

我的下一个问题是,我是否应该存储2个列表。一个清单   讲座和一个教程列表,而不是一个会话列表?这是   因为会话列表对我没用,我必须遍历   每次获取有关讲课和教程的信息。在那儿   一种我无法获得所有讲座对象的方式?

您回答了自己的问题。
当您开始编写过于复杂的样板代码以使应该变得简单的事情(例如,在刚刚添加的对象列表上进行迭代)时,表明您应该退后一步并重新设计它。

通过引入Enrolment.addSession(Session session), 您引入了不良的抽象:

public class Enrolment {

    private List<Session> sessions;

    public Enrolment() {
        this.sessions = new ArrayList<>();
    }

    public addSession(Session session) {
        this.sessions.add(session);
    }
}

Lecture的角度来看,您不想统一处理TutorialEnrolment,所以只因为它们不合并在同一List中它们依赖于相同的接口(Session)。
在需要时必须使用抽象,而不是系统地使用抽象,因为这是可能的。
您不是将所有对象都添加到“对象列表”中,因为所有对象都是对象吗?否

而不是从API方法及其实现中创建这种区别:

public class Enrolment {

    private List<Conference> conferences = new ArrayList<>();
    private List<Tutorial> tutorials = new ArrayList<>();


    public addConference(Conference conference) {
        this.conferences.add(conference);
    }

    public addTutorial(Tutorial tutorial) {
        this.tutorials.add(tutorial);
    }
}

并使用它:

Lecture morningLec = new Lecture(900, "Dr. Mike");
newEnrolment.addLecture(morningLec);

Tutorial afternoonTut = new Tutorial(1400, "John Smith", 3);
newEnrolment.addTutorial(afternoonTut);

请注意,您可能会遇到需要对某些处理进行统一处理的Tutorial和Lecture,而对于其他处理则需要对其进行区分的情况。
在这种情况下,您可以使用一些常用方法:

  • instanceOf:易于使用,但也易于使代码变脆。例如,稍后您可以在Session层次结构中添加一个新的子类,并且在不知道它的情况下,该子类的实例可以在某些处理中包括或排除,而编译器不会警告您。

  • 提供了一个抽象方法,该方法返回布尔值或枚举来传达对象的性质(例如:isLecture())。比instanceOf更强大,因为编译器限制您重写此方法,但是如果添加了多个子类并且过滤器不仅位于Lecture上,而且还Lecture上,则可能导致易于出错的代码和另一种类型。因此,我希望这种方式在过滤条件保持简单的同时。

  • 定义了三个列表:一个用于演讲,另一个用于会议,另一个包含应统一处理的所有列表。更复杂的方法,但也更可靠。我只会在复杂/不断变化的过滤条件的情况下支持它。

答案 2 :(得分:1)

也许您应该将其存储在两个列表中,就像:

{{1}}

是您需要的吗?

答案 3 :(得分:0)

        List<Lecture> l = newEnrolment.getSessions()
            .stream()
            .filter(s-> s.getClass().equals(Lecture.class))
            .map(session -> (Lecture) session)
            .collect(Collectors.toList());

!!!不要使用 typeof

答案 4 :(得分:0)

引用您的问题

  

这是因为会话列表对我无用。

因此,这可能不是拥有列表(?)的正确位置。

我的偏好是拥有


public interface Enrolment {
    public abstract addSession(Session session);
    public abstract getSessions();
}

并且List<LectureEnrolment>List<TutorialEnrolment>必须在各自的类中。(我将Lecture重命名为LectureEnrolment,并将Tutorial重命名为TutorialEnrolment

main()必须具有类似的内容,

Enrolment lectureEnrolment= new LectureEnrolment()

Enrolment tutorialEnrolement = new TutorialEnrolment()

根据需要分别呼叫addSession()getSession()

答案 5 :(得分:-1)

private List<Session> sessions;中的public List<Session> sessions;更改为class Enrolment

public static void main(String[] args) {
    ....
    var lecturesAndTutorials = newEnrolment.sessions.where(x => x.getType() == typeof(Lecture) || x.getType() == typeof(Tutorial));
    ....
}