Java-如何获得交错迭代器/集合

Java-如何获得交错迭代器/集合,java,collections,Java,Collections,假设我们异步接收来自3个生产者的字符串。一旦接收到一定数量的这些对象,我希望以交错方式对它们进行迭代,也就是说,如果接收到以下字符串: "a1" received from A, "a2" received from A, "c1" received from C, "a3" received from A, "b1" received from B, "b2" received from B, 我希望“交错”迭代器返回字符串,就像我们在迭代以下列表一样: List<String>

假设我们异步接收来自3个生产者的字符串。一旦接收到一定数量的这些对象,我希望以交错方式对它们进行迭代,也就是说,如果接收到以下字符串:

"a1" received from A,
"a2" received from A,
"c1" received from C,
"a3" received from A,
"b1" received from B,
"b2" received from B,
我希望“交错”迭代器返回字符串,就像我们在迭代以下列表一样:

List<String> interleavedList = {"a1", "b1", "c1", "a2", "c2", "a3"},
List interleavedList={“a1”、“b1”、“c1”、“a2”、“c2”、“a3”},
到目前为止,我已经为每个制作人创建了一个
列表
,然后通过使用3个列表迭代器(使用
列表
)对所有字符串进行“迭代”。这很好,但我认为有一个更简单的方法。。。也许在接收字符串时直接构造交错列表?但我看不出要使用哪个
集合
或哪个
比较器


请注意,我对为每个制作人创建一个列表,然后将3个列表合并到第4个交错列表中不太感兴趣,因为这可能不会节省时间。

您似乎希望对列表进行排序,首先由数字决定排序,其次是字母。Java没有排序列表,因为列表的本质是不排序的。但是,您可以使用带有自定义比较器的排序集:

SortedSet<String> sortedset = new TreeSet<String>(
        new Comparator<String>() {
            @Override
            public int compare(String e1, String e2) {
                int num1 = Integer.parseInt(e1.replaceAll("[^\\d.]", ""));
                int num2 = Integer.parseInt(e2.replaceAll("[^\\d.]", ""));
                if (num1 > num2) {
                    return 1;
                }
                else if (num1 < num2) {
                    return -1;
                }
                else {
                    String let1 = e1.replaceAll("[0-9]", "");
                    String let2 = e2.replaceAll("[0-9]", "");
                    return let1.compareTo(let2);
                }
            }
        });
SortedSet SortedSet=新树集(
新比较器(){
@凌驾
公共整数比较(字符串e1、字符串e2){
int num1=Integer.parseInt(e1.replaceAll(“[^\\d.]”,“”));
int num2=Integer.parseInt(e2.replaceAll(“[^\\d.]”,“”));
如果(num1>num2){
返回1;
}
否则如果(num1

当您迭代此集合时,您将获得问题中描述的顺序。

一个选项是根据对象到达的特定于生产者的索引将所有对象转储到
PriorityBlockingQueue

class Message {
   String data;
   long index;
}

PriorityBlockingQueue<Message> queue = new PriorityBlockingQueue<Message>(
  10,
  Comparator.comparing(m -> m.index)
); 

List<String> batch = new ArrayList<>(BATCH_SIZE);
for (;;) {
   for (int i = 0; i < BATCH_SIZE; i++) {
      batch.add(queue.take().data);
   }
   handleBatch(batch);
   batch.clear();
}
类消息{
字符串数据;
长指数;
}
PriorityBlockingQueue=新建PriorityBlockingQueue(
10,
比较器。比较(m->m.index)
); 
列表批次=新阵列列表(批次大小);
对于(;;){
对于(int i=0;i

注意,这假设一个无限队列;如果队列是非无限的,您必须添加一些逻辑来处理最后一批。

您可以使用自定义的
比较器将字符串添加到
PriorityQueue
。在这种情况下,添加元素时,元素将自动排序。
下面是一个。

我最近遇到了类似的问题,下面是我得出的结论(只需依次从每个迭代器中提取,直到所有迭代器都耗尽,无需排序):

import java.util.Collection;
导入java.util.Iterator;
公共类交织器实现迭代器{
静态类节点{
节点下一步;
节点前置;
最终K值;
节点(K值){
这个值=值;
}
公共void setNext(节点next){
this.next=next;
}
公共void setPrev(节点prev){
this.prev=prev;
}
}
专用节点;
公共交织器(集合迭代器){
Node prev=null;
for(迭代器迭代器:迭代器){
如果(!iterator.hasNext()){
继续;
}
节点当前=新节点(迭代器);
如果(上一个!=null){
上一次设置下一次(当前);
当前设置prev(prev);
}否则{
节点=当前;
}
prev=当前值;
}
如果(上一个!=null){
上一个设置下一个(节点);
node.setPrev(prev);
}
}
@凌驾
公共布尔hasNext(){
返回node.value.hasNext();
}
@凌驾
公共交通工具{
T res=node.value.next();
updateNode();
返回res;
}
私有void updateNode(){
Node nextNode=Node.next;
if(node.value.hasNext()){
node=nextNode;
}else if(节点!=nextNode){
node.prev.next=nextNode;
nextNode.prev=node.prev;
node=nextNode;
}
}
}

您能告诉我们更多关于效率的信息吗?例如,使用a,您可以实现这一点,但是,这会减慢生产商的速度。另一方面,使用您提到的列表完全是省时的。它会占用一些内存,您可以通过子类java.util.Iterator来实现这一点。如果使用Java8,您是否尝试过在流中交错字符串?生产者是否有时间完成他们的工作?你能等一下迭代最终结果吗?
import java.util.Collection;
import java.util.Iterator;

public class InterleavedIterator<T> implements Iterator<T> {

  static class Node<K> {
    Node<K> next;
    Node<K> prev;
    final K value;

    Node(K value) {
      this.value = value;
    }

    public void setNext(Node<K> next) {
      this.next = next;
    }

    public void setPrev(Node<K> prev) {
      this.prev = prev;
    }
  }

  private Node<Iterator<T>> node;

  public InterleavedIterator(Collection<Iterator<T>> iterators) {
    Node<Iterator<T>> prev = null;
    for (Iterator<T> iterator : iterators) {
      if (!iterator.hasNext()) {
        continue;
      }
      Node<Iterator<T>> current = new Node<>(iterator);
      if (prev != null) {
        prev.setNext(current);
        current.setPrev(prev);
      } else {
        node = current;
      }
      prev = current;
    }
    if (prev != null) {
      prev.setNext(node);
      node.setPrev(prev);
    }
  }

  @Override
  public boolean hasNext() {
    return node.value.hasNext();
  }

  @Override
  public T next() {
    T res = node.value.next();
    updateNode();
    return res;
  }

  private void updateNode() {
    Node<Iterator<T>> nextNode = node.next;
    if (node.value.hasNext()) {
      node = nextNode;
    } else if (node != nextNode) {
      node.prev.next = nextNode;
      nextNode.prev = node.prev;
      node = nextNode;
    }
  }
}