Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-apps-script/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从流中收集对_Java_Java Stream_Streamex - Fatal编程技术网

Java 从流中收集对

Java 从流中收集对,java,java-stream,streamex,Java,Java Stream,Streamex,我有一个像这样的对象流: "0", "1", "2", "3", "4", "5", 如何将其转换为成对流: { new Pair("0", "1"), new Pair("2", "3"), new Pair("4", "5")}. 流大小未知。我正在从一个可能很大的文件中读取数据。我只有迭代器到集合,我使用拆分器将迭代器转换为流。 我知道以下是使用StreamX处理相邻对的答案: 这可以在java或StreamEx中完成吗? 谢谢这不是自然的合身,但你可以 List input = ..

我有一个像这样的对象流:

"0", "1", "2", "3", "4", "5",
如何将其转换为成对流:

{ new Pair("0", "1"), new Pair("2", "3"), new Pair("4", "5")}.
流大小未知。我正在从一个可能很大的文件中读取数据。我只有迭代器到集合,我使用拆分器将迭代器转换为流。 我知道以下是使用StreamX处理相邻对的答案: 这可以在java或StreamEx中完成吗?
谢谢

这不是自然的合身,但你可以

List input = ...
List<Pair> pairs = IntStream.range(0, input.size() / 2)
                            .map(i -> i * 2)
                            .mapToObj(i -> new Pair(input.get(i), input.get(i + 1)))
                            .collect(Collectors.toList());
列表输入=。。。
列表对=IntStream.range(0,input.size()/2)
.map(i->i*2)
.mapToObj(i->新对(input.get(i),input.get(i+1)))
.collect(Collectors.toList());
要在流中创建对,您需要一个有状态的lambda,这通常应该避免,但可以做到。注意:这仅在流为单线程时有效。i、 e.不平行

Stream<?> stream = 
assert !stream.isParallel();
Object[] last = { null };
List<Pair> pairs = stream.map(a -> {
        if (last[0] == null) {
            last[0] = a;
            return null;
        } else {
            Object t = last[0];
            last[0] = null;
            return new Pair(t, a);
        }
     }).filter(p -> p != null)
       .collect(Collectors.toList());
assert last[0] == null; // to check for an even number input.
Stream=
断言!stream.isParallel();
对象[]last={null};
列表对=stream.map(a->{
如果(最后[0]==null){
最后[0]=a;
返回null;
}否则{
对象t=最后一个[0];
last[0]=null;
返回新对(t,a);
}
}).filter(p->p!=null)
.collect(Collectors.toList());
断言最后一个[0]==null;//检查偶数输入。

只需用流替换
IntStream.range(1101)
(您不需要知道流的大小)-

import java.util.ArrayList;
导入java.util.List;
导入java.util.stream.IntStream;
公共类TestClass{
公共静态void main(字符串[]args){
最后一对=新对();
最终列表pairList=newarraylist();
IntStream.range(1101)
.map(i->{
if(pair.a==null){
a=i;
返回0;
}否则{
b=i;
返回1;
}
})
.filter(i->i==1)
.forEach(i->{
pairList.add(新对(Pair));
pair.reset();
});
pairList.stream().forEach(p->System.out.print(p+“”));
}
静态类对{
公共目标a;
公共目标b;
公共对(){
}
公共对(对源){
此.a=原.a;
此.b=原始.b;
}
无效重置(){
a=零;
b=零;
}
@凌驾
公共字符串toString(){
返回“{”+a+”,“+b+'}”;
}
}
}
如果您不想收集元素 问题的标题是从流中收集对,因此我假设您确实想要收集这些对,但您评论:


您的解决方案是有效的,问题是它将数据从文件加载到PairList,然后我可以使用此集合中的流来处理对。我不能这样做,因为数据可能太大,无法存储在内存中

这里有一种不用收集元素的方法

迭代器转换为迭代器,并从中将流转换为成对流相对简单

  /**
   * Returns an iterator over pairs of elements returned by the iterator.
   * 
   * @param iterator the base iterator
   * @return the paired iterator
   */
  public static <T> Iterator<List<T>> paired(Iterator<T> iterator) {
    return new Iterator<List<T>>() {
      @Override
      public boolean hasNext() {
        return iterator.hasNext();
      }

      @Override
      public List<T> next() {
        T first = iterator.next();
        if (iterator.hasNext()) {
          return Arrays.asList(first, iterator.next());
        } else {
          return Arrays.asList(first);
        }
      }
    };
  }

  /**
   * Returns an stream of pairs of elements from a stream.
   * 
   * @param stream the base stream
   * @return the pair stream
   */
  public static <T> Stream<List<T>> paired(Stream<T> stream) {
    return StreamSupport.stream(Spliterators.spliteratorUnknownSize(paired(stream.iterator()), Spliterator.ORDERED),
        false);
  }

  @Test
  public void iteratorAndStreamsExample() {
    List<String> strings = Arrays.asList("a", "b", "c", "d", "e", "f");
    Iterator<List<String>> pairs = paired(strings.iterator());
    while (pairs.hasNext()) {
      System.out.println(pairs.next());
      // [a, b]
      // [c, d]
      // [e, f]
    }

    paired(Stream.of(1, 2, 3, 4, 5, 6, 7, 8)).forEach(System.out::println);
    // [1, 2]
    // [3, 4]
    // [5, 6]
    // [7, 8]
  }
注意,对于我们知道支持列表是新生成的用例(如本例),定义一个不防御地复制列表的PairList构造函数可能是值得的。不过,现在这并不是很重要。但是一旦我们这样做了,这个方法将是
收集,然后(toCollection(ArrayList::new),PairList::newNonDefensivelyCopiedPairList)

现在我们可以使用它:

  /**
   * Creates a pair list with collectingAndThen, toList(), and PairList::new
   */
  @Test
  public void example() {
    List<List<Integer>> intPairs = Stream.of(1, 2, 3, 4, 5, 6)
        .collect(toPairList());
    System.out.println(intPairs); // [[1, 2], [2, 3], [3, 4]]

    List<List<String>> stringPairs = Stream.of("a", "b", "c", "d")
        .collect(toPairList());
    System.out.println(stringPairs); // [[a, b], [b, c]]
  }
/**
*使用CollectingAnd、toList()和PairList::new创建对列表
*/
@试验
公共无效示例(){
List intPairs=Stream.of(1,2,3,4,5,6)
.收集(toPairList());
System.out.println(intPairs);//[[1,2],[2,3],[3,4]]
列表字符串对=流(“a”、“b”、“c”、“d”)
.收集(toPairList());
System.out.println(stringPairs);//[[a,b],[b,c]]
}
下面是一个完整的源文件,其中包含一个可运行的示例(作为JUnit测试):

package-ex;
导入java.util.AbstractList;
导入java.util.ArrayList;
导入java.util.array;
导入java.util.List;
导入java.util.Objects;
导入java.util.stream.Collector;
导入java.util.stream.collector;
导入java.util.stream.stream;
导入org.junit.Test;
公共类对收集器{
/**
*以成对方式显示其元素列表上的视图。
* 
*@param元素类型
*/
静态类PairList扩展了AbstractList{
私人最终清单要素;
/**
*创建一个新的配对列表。
* 
*@param-elements这些元素
* 
*如果元素为null,@将引发NullPointerException
*如果元素的长度不是偶数,@将引发IllegalArgumentException
*/
公共成对列表(列表元素){
requirennull(元素,“元素不得为空”);
this.elements=新的ArrayList(元素);
if(this.elements.size()%2!=0){
抛出新的IllegalArgumentException(“元素数必须具有偶数大小”);
}
}
@凌驾
公共列表获取(int索引){
返回Arrays.asList(elements.get(index),elements.get(index+1));
}
@凌驾
公共整数大小(){
返回元素。size()/2;
}
}
/**
*返回收集到对列表的收集器。
* 
*@归还催收员
*/
公共静态收集器toPairList(){
返回Collectors.collectingAndThen(Collectors.toList(),PairList::new);
}
/**
*使用CollectingAnd、toList()和PairList::new创建对列表
*/
@试验
公共无效示例(){
List intPairs=Stream.of(1,2,3,4,5,6)
.收集(toPairList());
System.out.printl
  /**
   * A view on a list of its elements as pairs.
   * 
   * @param <T> the element type
   */
  static class PairList<T> extends AbstractList<List<T>> {
    private final List<T> elements;

    /**
     * Creates a new pair list.
     * 
     * @param elements the elements
     * 
     * @throws NullPointerException if elements is null
     * @throws IllegalArgumentException if the length of elements is not even
     */
    public PairList(List<T> elements) {
      Objects.requireNonNull(elements, "elements must not be null");
      this.elements = new ArrayList<>(elements);
      if (this.elements.size() % 2 != 0) {
        throw new IllegalArgumentException("number of elements must have even size");
      }
    }

    @Override
    public List<T> get(int index) {
      return Arrays.asList(elements.get(index), elements.get(index + 1));
    }

    @Override
    public int size() {
      return elements.size() / 2;
    }
  }
  /**
   * Returns a collector that collects to a pair list.
   * 
   * @return the collector
   */
  public static <E> Collector<E, ?, PairList<E>> toPairList() {
    return Collectors.collectingAndThen(Collectors.toList(), PairList::new);
  }
  /**
   * Creates a pair list with collectingAndThen, toList(), and PairList::new
   */
  @Test
  public void example() {
    List<List<Integer>> intPairs = Stream.of(1, 2, 3, 4, 5, 6)
        .collect(toPairList());
    System.out.println(intPairs); // [[1, 2], [2, 3], [3, 4]]

    List<List<String>> stringPairs = Stream.of("a", "b", "c", "d")
        .collect(toPairList());
    System.out.println(stringPairs); // [[a, b], [b, c]]
  }
package ex;

import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.junit.Test;

public class PairCollectors {

  /**
   * A view on a list of its elements as pairs.
   * 
   * @param <T> the element type
   */
  static class PairList<T> extends AbstractList<List<T>> {
    private final List<T> elements;

    /**
     * Creates a new pair list.
     * 
     * @param elements the elements
     * 
     * @throws NullPointerException if elements is null
     * @throws IllegalArgumentException if the length of elements is not even
     */
    public PairList(List<T> elements) {
      Objects.requireNonNull(elements, "elements must not be null");
      this.elements = new ArrayList<>(elements);
      if (this.elements.size() % 2 != 0) {
        throw new IllegalArgumentException("number of elements must have even size");
      }
    }

    @Override
    public List<T> get(int index) {
      return Arrays.asList(elements.get(index), elements.get(index + 1));
    }

    @Override
    public int size() {
      return elements.size() / 2;
    }
  }

  /**
   * Returns a collector that collects to a pair list.
   * 
   * @return the collector
   */
  public static <E> Collector<E, ?, PairList<E>> toPairList() {
    return Collectors.collectingAndThen(Collectors.toList(), PairList::new);
  }

  /**
   * Creates a pair list with collectingAndThen, toList(), and PairList::new
   */
  @Test
  public void example() {
    List<List<Integer>> intPairs = Stream.of(1, 2, 3, 4, 5, 6)
        .collect(toPairList());
    System.out.println(intPairs); // [[1, 2], [2, 3], [3, 4]]

    List<List<String>> stringPairs = Stream.of("a", "b", "c", "d")
        .collect(toPairList());
    System.out.println(stringPairs); // [[a, b], [b, c]]
  }    
}
 static class Paired<T> extends AbstractSpliterator<Pair<T>> {

    private List<T> list = new ArrayList<>(2);

    private final Iterator<T> iter;

    public Paired(Iterator<T> iter) {
        super(Long.MAX_VALUE, 0);
        this.iter = iter;
    }

    @Override
    public boolean tryAdvance(Consumer<? super Pair<T>> consumer) {
        getBothIfPossible(iter);
        if (list.size() == 2) {
            consumer.accept(new Pair<>(list.remove(0), list.remove(0)));
            return true;
        }
        return false;
    }

    private void getBothIfPossible(Iterator<T> iter) {
        while (iter.hasNext() && list.size() < 2) {
            list.add(iter.next());
        }
    }

}
 Iterator<Integer> iterator = List.of(1, 2, 3, 4, 5).iterator();
 Paired<Integer> p = new Paired<>(iterator);
 StreamSupport.stream(p, false)
            .forEach(pair -> System.out.println(pair.getLeft() + "  " + pair.getRight()));
(0,1)
(2,3)
(4,5)