Java 8 stream partitioningBy second predicate on false 条件
Java 8 stream partitioningBy second predicate on false condition
最近我一直在我的代码中尽可能多地使用流,但是我 运行 遇到了一个我还没有完全解决的问题。
我有一个简单的 class 叫做 '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,另一个列表包含 public 个具有会话 ID 的房屋。
使用传统循环我可以实现我想要的功能,但我希望能够将其转换为使用流。
下面的测试 class 包含两个测试,第一个测试 shouldProduceTwoListsWithOneElementEach
使用传统的 for each 循环并遍历房屋列表并生成两个列表,一个包含 privateHouses,另一个包含 public houses or houses with a sessionId.
第二个测试 shouldSeperateWhetherHouseIsPrivate
是我最初尝试使用流,目前测试在第二个断言上失败,因为 partitioningBy 逻辑仅拆分房屋对象是否私有,因此 public 没有会话的房子最终被添加到另一个列表,通过 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()
的计算结果为真,则 House
对象将添加到 Map<Boolean, List<House>> segregatedHouses
中,可以通过 segregatedHouses.get(true)
访问该对象。如果谓词的计算结果为 false,那么 House
将被添加到另一个列表中,有没有办法在将 House 添加到将通过 segregatedHouses.get(false)
访问的列表之前再次评估 House?
非常感谢任何帮助!
我相信第二部分,您只需要私人房屋或 public 且 hasSessionId 分为 2 个列表的房屋。
试试这个...
Map<Boolean, List<House>> segregatedHouses = houses.stream()
.filter(p -> p.isPrivate() || p.hasSessionId())
.collect(Collectors.partitioningBy(p -> p.isPrivate()))
最近我一直在我的代码中尽可能多地使用流,但是我 运行 遇到了一个我还没有完全解决的问题。
我有一个简单的 class 叫做 '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,另一个列表包含 public 个具有会话 ID 的房屋。
使用传统循环我可以实现我想要的功能,但我希望能够将其转换为使用流。
下面的测试 class 包含两个测试,第一个测试 shouldProduceTwoListsWithOneElementEach
使用传统的 for each 循环并遍历房屋列表并生成两个列表,一个包含 privateHouses,另一个包含 public houses or houses with a sessionId.
第二个测试 shouldSeperateWhetherHouseIsPrivate
是我最初尝试使用流,目前测试在第二个断言上失败,因为 partitioningBy 逻辑仅拆分房屋对象是否私有,因此 public 没有会话的房子最终被添加到另一个列表,通过 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()
的计算结果为真,则 House
对象将添加到 Map<Boolean, List<House>> segregatedHouses
中,可以通过 segregatedHouses.get(true)
访问该对象。如果谓词的计算结果为 false,那么 House
将被添加到另一个列表中,有没有办法在将 House 添加到将通过 segregatedHouses.get(false)
访问的列表之前再次评估 House?
非常感谢任何帮助!
我相信第二部分,您只需要私人房屋或 public 且 hasSessionId 分为 2 个列表的房屋。
试试这个...
Map<Boolean, List<House>> segregatedHouses = houses.stream()
.filter(p -> p.isPrivate() || p.hasSessionId())
.collect(Collectors.partitioningBy(p -> p.isPrivate()))