Java 8 流 - 在流操作中使用原始流对象

4
我正在对一个整数数组运行“Stream”操作。 然后我创建了一个“Cell”对象进行一些操作并应用了过滤器, 我想创建一个从整数到“Cell”的映射,只包含有效的“Cell”。 大致如下:
List<Integer> type = new ArrayList<>();

Map<Integer, Cell> map =
  list.stream()
    .map(x -> new Cell(x+1, x+2))        // Some kind of Manipulations
    .filter(cell->isNewCellValid(cell))  // filter some
    .collect(Collectors.toMap(....));

在流操作期间是否可以使用原始流对象?

2个回答

6

如果你的map操作创建了一些包含原始Stream元素的实例,那么你可以存储这些实例。

例如:

Map<Integer, Cell> map =
  list.stream()
      .map(x -> new SomeContainerClass(x,new Cell(x+1, x+2)))
      .filter(container->isNewCellValid(container.getCell()))
      .collect(Collectors.toMap(c->c.getIndex(),c->c.getCell()));

有一些现有的类可以用来代替创建自己的SomeContainerClass,比如AbstractMap.SimpleEntry

Map<Integer, Cell> map =
  list.stream()
      .map(x -> new AbstractMap.SimpleEntry<Integer,Cell>(x,new Cell(x+1, x+2)))
      .filter(e->isNewCellValid(e.getValue()))
      .collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue));

1
我一直在想,这种模式是否违反了流操作的首选无状态性。但我想这没关系... - daniu
@daniu 我不确定你的意思是什么。我的建议解决方案中是否有任何状态?您必须保留流中的所有元素,这些元素是生成所需输出所需的所有数据。 - Eran
1
不,你是对的,按照你发布的方式没有问题。 我在考虑一个“ContainerClass”,它在流创建之前创建,然后被馈送流的元素,因此在处理过程中会改变其状态。 - daniu

1

在流操作中是否可以使用原始的流对象?

是的,直到您不使用map操作为止。

您需要一个Function<Cell,Integer>来恢复原始值。在您的示例中,它是(Cell cell) -> cell.getFirst() - 1

.collect(Collectors.toMap(cell -> cell.getFirst() - 1, Function.identity()));

我建议编写Function<Integer, Cell>Function<Cell, Integer>函数,而不是为单个流处理构建不必要的包装类:
final Function<Integer, Cell> xToCell = x -> new Cell(x + 1, x + 2);
final Function<Cell, Integer> cellToX = cell -> cell.getX1() - 1;

final Map<Integer, Cell> map =
        list
                .stream()
                .map(xToCell)
                .filter(cell -> isNewCellValid(cell))
                .collect(Collectors.toMap(cellToX, Function.identity()));

当然,对于那些可以简单或直观地反转的操作来说,这是有效的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接