我希望根据谓词过滤列表,也要过滤她的子列表

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;  

class Hotel {
    private final String city;
    private final int numberOfStart;
    private final List<Room> rooms = new ArrayList<>();

    public String getCity(){return city;}
    public int  getNumberOfStart(){return numberOfStart;}
    public List<Room> getRooms(){return rooms;}
    public Hotel(String city, int numberOfStart) {
        this.city = city;
        this.numberOfStart = numberOfStart;
    }

    public void creatRooms(String roomNumber ,int numberOfbed,Double price)   {
        Room room = new Room(roomNumber,numberOfbed,price);
        this.rooms.add(room);
    }

    @Override
    public String toString() {
        return "Hotel{\n\t" +
                "city='" + city + '\'' +
                ", numberOfStart=" + numberOfStart +
                ", \n\trooms=" + rooms +
                "}\n\n";
    }
}

class Room {
    private final double price;
    private final int numberOfBed;
    private final String roomNumber;

    Room (String roomNumber,int numberOfBed, Double price){
        this.price=price;
        this.roomNumber=roomNumber;
        this.numberOfBed=numberOfBed;

    }

    public double getPrice() {return price;}
    public int getNumberOfBed(){return numberOfBed;}

    @Override
    public String toString() {
        return "\n\t\tRoom{" +
                "price=" + price +'\'' +
                ", numberOfBed=" + numberOfBed +
                ", roomNumber='" + roomNumber +
                '}';
    }
}

public class Main  {

    /**
     * @param hotelList List search on a list of hotels.
     * @param city relates to the location of the hotel, if empty "", then the predicate will be true, and ignore the city parameter.
     * @param start concerns the quality of the hotel, if set to 0 then the predicate will be true, and ignore the start parameter.
     * @param priceMax
     * @param nbBed concerns the amount beds, ignored if set to 0
     * @return
     */
    public static List<Hotel> searchHotelRoom(List<Hotel> hotelList, String city, int start, Double priceMax, int nbBed) {

        //condition about city location and price on hotel list
        Predicate<Hotel> byCity = !city.isEmpty()? hotel -> hotel.getCity().equalsIgnoreCase(city) : hotel -> true;
        Predicate<Hotel> byStart =!(start==0)? hotel -> hotel.getNumberOfStart() == start:hotel -> true;

        //condition on room list
        Predicate<Room> byNbBed =!(nbBed==0)? room  -> (room.getNumberOfBed()== nbBed) :room -> false;
        Predicate<Room> byPrice = room ->  room.getPrice()<=priceMax;

        return hotelList.stream()
                .filter(byStart)
                .filter(byCity)
                .filter(room -> room.getRooms().stream().anyMatch(byPrice))
                .filter(room -> room.getRooms().stream().anyMatch(byNbBed))
                .collect(Collectors.toList());
    }

    public static void main(String[] args) {

        List<Hotel> hotelList = new ArrayList<>();

        //Dummy hotel data
        Hotel hotelA = new Hotel("Paris",4);
        hotelA.creatRooms("p12", 2, 150.);
        hotelA.creatRooms("p17", 1, 200.);
        hotelA.creatRooms("p15", 3, 50.);
        hotelList.add(hotelA);

        Hotel hotelB = new Hotel("Montpellier",4);
        hotelB.creatRooms("b12", 2, 20.);
        hotelB.creatRooms("b17", 1, 200.);
        hotelB.creatRooms("b15", 1, 40.);
        hotelB.creatRooms("b15", 1, 1.);
        hotelList.add(hotelB);

        Hotel hotelC = new Hotel("Toulouse",4);
        hotelC.creatRooms("c12", 21, 200.);
        hotelC.creatRooms("c17", 11, 100.);
        hotelC.creatRooms("c15", 21, 50.);
        hotelC.creatRooms("c16", 30, 25.);
        hotelList.add(hotelC);

        //System.out.println("Hotels List\n");
        //hotelList.forEach(System.out::println);

        List<Hotel> result= searchHotelRoom(hotelList,"",0,200.,2);
        System.out.println("Result of search");
        result.forEach(System.out::println);
    }

}

搜索功能不像我希望的那样工作,有一些不一致 例如,对于

List<Hotel> result= searchHotelRoom(hotelList,"paris",0,200.,1);

我有这样的结果

Result of search
Hotel{
    city='Paris', numberOfStart=4, 
    rooms=[
        Room{price=150.0', numberOfBed=2, roomNumber='p12}, 
        Room{price=200.0', numberOfBed=1, roomNumber='p17}, 
        Room{price=50.0', numberOfBed=3, roomNumber='p15}]}

但我想要像这样的东西

Result of search
Hotel{
    city='Paris', numberOfStart=4, 
    rooms=[
            Room{price=200.0', numberOfBed=1, roomNumber='p17}}

而且似乎我在两个过滤器之间没有and logic

List<Hotel> result= searchHotelRoom(hotelList,"paris",0,200.,2);

必须返回空洞,但我有一个结果

在许多wine 店里

List<Hotel> result= searchHotelRoom(hotelList,"",0,200.,1);

我有过

Result of search
Hotel{
    city='Paris', numberOfStart=4, 
    rooms=[
        Room{price=150.0', numberOfBed=2, roomNumber='p12}, 
        Room{price=200.0', numberOfBed=1, roomNumber='p17}, 
        Room{price=50.0', numberOfBed=3, roomNumber='p15}]}


Hotel{
    city='Montpellier', numberOfStart=4, 
    rooms=[
        
        Room{price=200.0', numberOfBed=1, roomNumber='b17}, 

但我想要的是

Result of search
Hotel{
    city='Paris', numberOfStart=4, 
    rooms=[
        Room{price=200.0', numberOfBed=1, roomNumber='p17} 
}


Hotel{
    city='Montpellier', numberOfStart=4, 
    rooms=[
    
        Room{price=200.0', numberOfBed=1, roomNumber='b17} 
}

in search method anyMatch return a boolean but i want list of room,
so i have trie somme stuff on my searh methode like , but doesn't work

 .filter(room -> room.getRooms().stream().filter(byPrice))

有谁能帮我个忙吗?

推荐答案

searchHotelRoom()%的方法存在一个逻辑缺陷.

我想返回类型应该是List<Room>(而不是Hotel的列表).这样想一想:当你需要找一个住宿的地方时,你不是要订整个wine 店,而是需要一个房间.searchHotelRoom()中有no need个实例根据符合条件的房间生成新的Hotel个实例,我们需要这些房间本身.

您可能希望保留某个房间属于哪个wine 店的信息,这个问题可以在类设计级别上解决(and should be).为此,您可以向Room类引入一个属性.例如:String hotelName,或者一个房间可以包含对Hotel实例的引用,但在这种情况下,在实现toString()hashCode()这样的方法时需要be careful,因为您可能会以无限递归结束.

因此,要获得与给定条件匹配的ListRoom,您需要应用与wine 店相关的过滤器,然后将wine 店流Stream<Hotel>转换为房间流Stream<Room>.为此,您可以使用flatMap()操作(或Java 16 mapMulti()),这意味着要执行one-to-many转换,并期望function产生一个Stream作为参数.

然后是与房间相关的过滤器,并收集结果.

而不是两次应用filter(),您可以使用Precate.and()链接谓词,这相当于逻辑AND &&.

public static List<Room> searchHotelRoom(List<Hotel> hotelList, String city, int start, Double priceMax, int nbBed) {
    
    //condition about city location and price on hotel list
    Predicate<Hotel> byCity = !city.isEmpty()? hotel -> hotel.getCity().equalsIgnoreCase(city) : hotel -> true;
    Predicate<Hotel> byStart = !(start == 0)? hotel -> hotel.getNumberOfStart() == start:hotel -> true;
    
    //condition on room list
    Predicate<Room> byNbBed = !(nbBed == 0)? room  -> (room.getNumberOfBed() == nbBed) :room -> false;
    Predicate<Room> byPrice = room ->  room.getPrice() <= priceMax;
    
    return hotelList.stream()                        // Stream<Hotel>
        .filter(byStart.and(byCity))
        .flatMap(hotel -> hotel.getRooms().stream()) // Stream<Room>
        .filter(byPrice.and(byNbBed))
        .toList(); // for Java 16 or collect(Collectors.toList())
}

Java相关问答推荐

使用Apache Poi MQLSlideShow,在XSLFTable表中,我们可以在文本段落后面的每个单元格中包含圆角矩形吗?

如何在返回bigint []值的子查询中使用any?

缩小画布比例后更改滚动窗格的内部大小

我无法将附件发送到NetBeans之外

对运行在GraalVM-21上的JavaFX应用程序使用分代ZGC会警告不支持JVMCI,为什么?

Java FX中的河内之塔游戏-在游戏完全解决之前什么都不会显示

如何找到MongoDB文档并进行本地化?

Com.example.service.QuestionService中的构造函数的参数0需要找不到的类型为';com.example.Dao.QuestionDao;的Bean

通过Spring Security公开Spring Boot执行器端点

我如何解释这个错误?必需类型:供应商R,提供:收集器对象,捕获?,java.util.List java.lang.Object>>

基于接口的投影、原生查询和枚举

舰队运行配置Maven版本

在应用程序运行时更改LookAndFeel

将BlockingQueue+守护程序线程替换为执行器

JavaFX,GridPane:在GridPane的列中生成元素将保持所有列的宽度

保持标题窗格的箭头可见,即使设置为不可折叠

没有Google Play服务,Firebase Auth无法工作

spring 数据Elastic search 与 spring 启动数据Elastic search 之间的区别是什么?

[Guice/MissingImplementation]:未绑定任何实现

如何使用命令行为Java应用程序生成烟雾测试用例