拆分字符串,将其flatMapping并使用Java流创建对象?

问题描述 投票:0回答:2

我有2个这样的课程:

public class Seat extends Moviefiable {

        private int number;
        private Hall hall;

        public Seat(int id, boolean active, int number, Hall hall) {
            super(id, active);
            this.number = number;
            this.hall = hall;
        }

        public Seat() {this(-1, false, -1, null);}

        public static Seat getById(int idSeat) throws SQLException {
            Seat seat = SeatDAO.getById(idSeat);
            return seat;
        }
}

public class Ticket extends Moviefiable {

private Projection projection;
private Seat seat;
private LocalDateTime purchasingDate;
private User user;

public Ticket(int id, boolean active, Projection projection, Seat seat, LocalDateTime purchasingDate, User user) {
    super(id, active);
    this.projection = projection;
    this.seat = seat;
    this.purchasingDate = purchasingDate;
    this.user = user;
}

public Ticket() {this(-1, false, null, null, null, null);}

现在,我需要创建两个或多个Tickets,具体取决于loggedInUser选择的票证数量。从我的JSP页面上,我将得到如下内容:

String uri = request.getQueryString(); //uri looks like this: seats=2&seats=3

我想为两个Ticket对象创建两个Seat对象。在uri字符串中,字符2和3是席位的主键。

想法是使用Java流执行拆分和创建对象。这是我到目前为止。

ArrayList<Ticket> newTicketsForSeats = Stream.of(uri.split("&"))
                   .map(s -> s.split("seats=")[1])
                   //.flatMap(Arrays::stream)
                   .mapToInt(Integer::valueOf)
                   .mapToObj(s -> {
                    try {
                        return new Ticket(-1, true, projection, SeatDAO.getById(s), 
                                 LocalDateTime.now(), loggedInUser);
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                        return null;
                    }
                })
                   .collect(Collectors.toCollection(ArrayList::new));

当我进行测试时,像这样查看我得到的输出:

Stream.of(uri.split("&"))
    .map(s -> s.split("seats=")[1])
    .mapToInt(Integer::valueOf)
    .forEach(System.out::println); //2 3

哪个很好。但是当我在上面运行代码时,我得到了:

java.lang.ArrayIndexOutOfBoundsException: 1
at servlets.ConfirmPurchaseServlet.lambda$0(ConfirmPurchaseServlet.java:62)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)

projection也是我获得的对象,这只是参考,它在Servlet中的其他位置。 loggedInUser我从会议中获得。我是Java流的新手,任何其他解释都将是非常好的。

我知道map()需要IntUnaryOperator lambda表达式,类似这样:

s -> s * 10

我不知道如何从int(Seat的主键)“映射”到Seat对象。

干杯。

java java-stream flatmap
2个回答
0
投票

您的主要问题是您试图将流输出分配给ArrayListCollectors.toList()返回无法预期是特定实现的List

所以要么这样做:

List<SomeClass> list = ...collect(Collectors.toList());

或此

ArrayList<SomeClass> list = ... collect(Collectors.toCollection(ArrayList::new));

以下内容应该可以使用,但是可能需要根据您的其他类进行一些调整。

ArrayList<Ticket> newTicketsForSeats = Stream.of(uri.split("&"))
               .map(s -> s.split("seats="))
               .flatMap(Arrays::stream)
               .mapToInt(Integer::valueOf)
               .mapToObj(s -> new Ticket(-1, true, projection, SeatDAO.getById(s), 
                     LocalDateTime.now(), loggedInUser))
               .collect(Collectors.toCollection(ArrayList::new));

0
投票

这些都可能有效:

List<Ticket> newTicketsForSeats = Stream.of(uri.split("&"))
        .map(s -> s.replace("seats=", ""))
        .mapToInt(Integer::valueOf)
        .mapToObj(s -> new Ticket(-1, true, projection, SeatDAO.getById(s), LocalDateTime.now(), loggedInUser))
        .collect(Collectors.toList());

List<Ticket> newTicketsForSeats = Stream.of(uri.split("&"))
        .map(s -> s.replace("seats=", ""))
        .map(s -> new Ticket(-1, true, projection, SeatDAO.getById(Integer.valueOf(s)), LocalDateTime.now(), loggedInUser))
        .collect(Collectors.toList());

BTW:您似乎没有与签名匹配的Ticket构造函数:

Ticket(int, boolean, Projection, Seat, LocalDateTime, boolean)

0
投票

我在解释问题时犯了一个错误。

我的原始字符串uri

String uri = request.getQueryString(); //seats=2&seats=3

这是错误的。我的实际字符串看起来像这样

//projection=1&seats=2&seats=3

我忘记了我要发送选定电影放映的主键,白痴。

现在,我设法获得了期望的结果:

ArrayList<Ticket> newTicketsForSeats = 
                Stream.of( String.join("", Arrays.copyOfRange(uri.split("&"), 1, uri.split("&").length)))
                      .map(s -> s.split("seats="))
                      .flatMap(Arrays::stream)
                      .filter(x -> !x.contentEquals(""))
                      .mapToInt(Integer::valueOf)
                      .mapToObj(s -> {
                       try {
                            return new Ticket(-1, true, projection, SeatDAO.getById(s), 
                                         LocalDateTime.now(), loggedInUser);
                           } catch (SQLException e) { e.printStackTrace(); return null;}

                           })
                           .collect(Collectors.toCollection(ArrayList::new));

Tho,我不喜欢Arrays.copyOfRange(),据我所知,它太宽泛了。也许有机会解决这个问题?

© www.soinside.com 2019 - 2024. All rights reserved.