Java 8流分区是关于错误条件的第二个谓词

时间:2015-05-23 20:01:22

标签: java java-8 java-stream

我最近在代码中尽可能地使用了流,但是我遇到了一个我无法解决的问题。

我有一个名为' Listing'的简单类:

package models;

public class House {

private boolean isPrivate;
private Integer views;
private boolean hasSessionId;

public Listing(boolean isPrivate, Integer views, boolean hasSessionId) {
    this.isPrivate = isPrivate;
    this.views = views;
    this.hasSessionId = hasSessionId;
}

public boolean hasSessionId() {
    return hasSessionId;
}

public boolean isPublic() {
    return !isPrivate;
}

public boolean isPrivate() {
    return isPrivate;
}

public Integer getViews() {
    return views;
}

}

我有一个房子列表,我想要制作一个包含两个列表的地图,其中的房屋通过某些条件隔离,我希望一个列表包含私人住宅,无论他们是否有会话ID,另一个列表包含公共有会话ID的房子。

使用传统循环我可以实现我想要的功能,但我希望能够将其转换为使用流。

下面的测试类包含两个测试,第一个测试shouldProduceTwoListsWithOneElementEach使用传统的每个循环并遍历房屋列表并生成两个列表,一个包含privateHouses,另一个包含公共房屋或带有sessionId的房屋

第二个测试shouldSeperateWhetherHouseIsPrivate是我最初使用流的尝试,目前测试在第二个断言失败,因为partitioningBy逻辑只是拆分房屋对象是否是私有的,因此是一个公共房屋做没有会话最终被添加到另一个列表,通过segregatedHouses.get(false)访问。

package models;

import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.junit.Before;
import org.junit.Test;

public class ListingsTest {

private List<House> houses;

@Before
public void setUp() {
    House publicListingWithSession = new House(false, 1, true);
    House privateListingWithoutSession = new House(true, 1, false);
    House publicListingWithNoViewsWithoutSession = new House(false, 0, false);

    this.houses = new ArrayList<House>();
    this.houses.add(publicListingWithSession);
    this.houses.add(privateListingWithoutSession);
    this.houses.add(publicListingWithNoViewsWithoutSession);
}

@Test
public void shouldProduceTwoListsWithOneElementEach() {
    List<House> privateHouses = new ArrayList<House>();
    List<House> publicHousesOrHasSessionId = new ArrayList<House>();

    for (House listing : houses) {
        if (listing.isPrivate()) {
            privateHouses.add(listing);
        } else if (listing.getViews() > 0 || listing.hasSessionId()) {
            publicHousesOrHasSessionId.add(listing);
        }
    }
    assertEquals(1, privateHouses.size());
    assertEquals(1, publicHousesOrHasSessionId.size());
}

@Test
public void shouldSeperateWhetherHouseIsPrivate() {
    Map<Boolean, List<House>> segregatedHouses = houses.stream()//
            .collect(Collectors.partitioningBy(p -> p.isPrivate()));

    assertEquals(1, segregatedHouses.get(true).size());
    assertEquals(1, segregatedHouses.get(false).size());
}

}

因此,如果谓词p -> p.isPrivate()的计算结果为true,则House对象将添加到Map<Boolean, List<House>> segregatedHouses,可以通过segregatedHouses.get(true)访问。如果谓词的计算结果为false,那么House会被添加到另一个列表中,是否有一种方法可以在将House添加到将通过segregatedHouses.get(false)访问的列表之前再次对其进行评估?

任何帮助非常感谢!

1 个答案:

答案 0 :(得分:3)

我相信在第二部分中,你只想要私有的房子或者是公共的房子,并且hasSessionId被分成2个列表。

试试这个......

Map<Boolean, List<House>> segregatedHouses = houses.stream()
        .filter(p -> p.isPrivate() || p.hasSessionId())
        .collect(Collectors.partitioningBy(p -> p.isPrivate()))