Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.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_Lazy Loading_Iterable_Enumerable - Fatal编程技术网

如何在java中以惰性方式连接两个集合?

如何在java中以惰性方式连接两个集合?,java,lazy-loading,iterable,enumerable,Java,Lazy Loading,Iterable,Enumerable,我有两个集合,我想返回一个IEnumerable,它是它们的串联。返回的枚举应该是惰性的,不应该修改两个初始集合(因此,我不想将两个集合复制到一个集合中,然后返回结果,因为这不是惰性的) 下面的代码是我想用Java实现但用c#编写的一个示例: 公共静态IEnumerable all() { List list1=新列表(){1,2,3}; List list2=新列表(){4,5,6}; 返回列表1.Concat(列表2); } 您可以使用以下方法: 将提供的iterable合并为单个itera

我有两个集合,我想返回一个IEnumerable,它是它们的串联。返回的枚举应该是惰性的,不应该修改两个初始集合(因此,我不想将两个集合复制到一个集合中,然后返回结果,因为这不是惰性的)

下面的代码是我想用Java实现但用c#编写的一个示例:

公共静态IEnumerable all()
{
List list1=新列表(){1,2,3};
List list2=新列表(){4,5,6};
返回列表1.Concat(列表2);
}
您可以使用以下方法:

将提供的iterable合并为单个iterable

返回的iterable有一个迭代器,它按照参数的顺序遍历元素,即iterables[0],iterables直到必要时才轮询源迭代器。

或方法:

将多个iterable合并为一个iterable。返回的iterable有一个迭代器,它遍历输入中每个iterable的元素在必要时才轮询输入迭代器。


C#IEnumerable Enumerable.Concat(IEnumerable, 数不清‌​)可以在
公共集合中找到:Iterable IterableUtils.chaineditable(Iterable这里有一个手动实现,返回一个
迭代器

public static <T> Iterator<T> concatIterator(Iterable<T> l1, Iterable<T> l2) {
    return new Iterator<>() {
        Iterator<T> it1 = l1.iterator();
        Iterator<T> it2 = l2.iterator();
        public boolean hasNext() {
            return it1.hasNext() || it2.hasNext();
        }
        public T next() {
            return it1.hasNext() ? it1.next() : it2.next();
        }
    }
}
公共静态迭代器concatIterator(Iterable l1,Iterable l2){
返回新的迭代器(){
迭代器it1=l1.Iterator();
迭代器it2=l2.Iterator();
公共布尔hasNext(){
返回it1.hasNext()| it2.hasNext();
}
公共交通工具{
返回it1.hasNext()?it1.next():it2.next();
}
}
}
你可以用它得到一个
Iterable

public static <T> Iterable<T> concatIterable(Iterable<T> l1, Iterable<T> l2) {
    return new Iterable<>() {
        public Iterator<T> iterator() {
            return concatIterator(l1, l2);
        }
    }
}
public static Iterable concaterable(Iterable l1,Iterable l2){
返回新的Iterable(){
公共迭代器迭代器(){
返回计数器(l1,l2);
}
}
}

如果您只需要
Iterable
,那么简单的
链应该适合您

class Chain<T> implements Iterable<T> {
    final Iterable<Iterable<T>> lists;

    public Chain(Iterable<T>... lists) {
        this.lists = Arrays.asList(lists);
    }

    @Override
    public Iterator<T> iterator() {
        return new Iterator<T>() {
            // Walks the lists.
            Iterator<Iterable<T>> i = lists.iterator();
            // Walks the list.
            Iterator<T> l = prime(i.hasNext() ? i.next().iterator() : null);

            @Override
            public boolean hasNext() {
                return l != null && l.hasNext();
            }

            @Override
            public T next() {
                if (hasNext()) {
                    T next = l.next();
                    l = prime(l);
                    return next;
                } else {
                    throw new NoSuchElementException("Chain exhausted.");
                }
            }

            private Iterator<T> prime(Iterator<T> l) {
                // Prepare for next time.
                while (l != null && !l.hasNext()) {
                    if (i.hasNext()) {
                        l = i.next().iterator();
                    } else {
                        l = null;
                    }
                }
                return l;
            }
        };
    }
}

public void test(String[] args) {
    Chain<Integer> chain = new Chain<>(
            Arrays.asList(),
            Arrays.asList(1, 2, 3),
            Arrays.asList(),
            Arrays.asList(4, 5, 6),
            Arrays.asList(7,8,9,10),
            Arrays.asList()
            );
    for (Integer i : chain) {
        System.out.println(i);
    }
}
类链实现了Iterable{
最终可编辑列表;
公共链(Iterable…列表){
this.lists=Arrays.asList(列表);
}
@凌驾
公共迭代器迭代器(){
返回新的迭代器(){
//浏览列表。
迭代器i=lists.Iterator();
//走在名单上。
迭代器l=prime(i.hasNext()?i.next()。迭代器():null);
@凌驾
公共布尔hasNext(){
返回l!=null&&l.hasNext();
}
@凌驾
公共交通工具{
if(hasNext()){
T next=l.next();
l=素数(l);
下一步返回;
}否则{
抛出新的NoSuchElementException(“链耗尽”);
}
}
专用迭代器素数(迭代器l){
//为下次做准备。
while(l!=null&&!l.hasNext()){
if(i.hasNext()){
l=i.next().iterator();
}否则{
l=零;
}
}
返回l;
}
};
}
}
公共无效测试(字符串[]args){
链=新链(
Arrays.asList(),
数组。asList(1,2,3),
Arrays.asList(),
数组。asList(4,5,6),
数组。asList(7,8,9,10),
Arrays.asList()
);
for(整数i:链){
系统输出打印LN(i);
}
}

您还可以对
列表
执行类似的工作,甚至可能对
集合

执行类似的工作。如果您的输入是列表,则
链接列表
下面的类可以对其进行包装

我必须将两个列表作为一个惰性列表提供给JAXB Marshaller,但它不适用于
Iterable
。要使用
maxOccurs=“unbounded”
JAXB创建元素,需要bean属性至少实现
java.util.Collection

该解决方案使用Apache Commons,但在Guava中有一个等价的
Iterables.concat()

import org.apache.commons.collections4.iterabluetils;
/**该类使多个列表在调用方看来像一个列表*/
public class/*NOSONAR*/ChainedList扩展了AbstractList实现了随机访问{
私人最终清单[]要素;
私有最终int[]endindex;
@安全变量
公共链接列表(最终列表…列表){
这个(Arrays.asList(lists));
}
@抑制警告(“未选中”)
public ChainedList(最终Iterable元素){
最终列表tmpElementsList=iterabluetils.toList(元素);
this.elements=tmpElementsList.toArray(新列表[tmpElementsList.size()]);
endIndexes=newint[this.elements.length];
int currentSize=0;
for(int i=0;i=大小()时引发
最终列表子列表=元素[partitionIndex];
//当索引为负数或最后一个子列表为空时引发
返回子列表.get(子索引);
}
@凌驾
公共E集(最终整数索引,最终E元素){
最终int partitionIndex=getPartitionIndex(索引);
最终int子索引=getSubIndex(分区索引,索引);
//当索引>=大小()时引发
最终列表子列表=元素[partitionIndex];
if(子索引<0 | | su
class Chain<T> implements Iterable<T> {
    final Iterable<Iterable<T>> lists;

    public Chain(Iterable<T>... lists) {
        this.lists = Arrays.asList(lists);
    }

    @Override
    public Iterator<T> iterator() {
        return new Iterator<T>() {
            // Walks the lists.
            Iterator<Iterable<T>> i = lists.iterator();
            // Walks the list.
            Iterator<T> l = prime(i.hasNext() ? i.next().iterator() : null);

            @Override
            public boolean hasNext() {
                return l != null && l.hasNext();
            }

            @Override
            public T next() {
                if (hasNext()) {
                    T next = l.next();
                    l = prime(l);
                    return next;
                } else {
                    throw new NoSuchElementException("Chain exhausted.");
                }
            }

            private Iterator<T> prime(Iterator<T> l) {
                // Prepare for next time.
                while (l != null && !l.hasNext()) {
                    if (i.hasNext()) {
                        l = i.next().iterator();
                    } else {
                        l = null;
                    }
                }
                return l;
            }
        };
    }
}

public void test(String[] args) {
    Chain<Integer> chain = new Chain<>(
            Arrays.asList(),
            Arrays.asList(1, 2, 3),
            Arrays.asList(),
            Arrays.asList(4, 5, 6),
            Arrays.asList(7,8,9,10),
            Arrays.asList()
            );
    for (Integer i : chain) {
        System.out.println(i);
    }
}
import org.apache.commons.collections4.IterableUtils;

/** This class makes multiple lists look like one to the caller. */
public class /* NOSONAR */ ChainedList<E> extends AbstractList<E> implements RandomAccess {

    private final List<E>[] elements;

    private final int[] endIndexes;

    @SafeVarargs
    public ChainedList(final List<E>... lists) {
        this(Arrays.asList(lists));
    }

    @SuppressWarnings("unchecked")
    public ChainedList(final Iterable<List<E>> elements) {
        final List<List<E>> tmpElementsList = IterableUtils.toList(elements);
        this.elements = tmpElementsList.toArray(new List[tmpElementsList.size()]);
        endIndexes = new int[this.elements.length];
        int currentSize = 0;
        for (int i = 0; i < this.elements.length; i++) {
            final List<E> curr = this.elements[i];
            final int sz = curr.size();
            endIndexes[i] = currentSize + sz;
            currentSize += sz;
        }
    }

    @Override
    public E get(final int index) {
        final int partitionIndex = getPartitionIndex(index);
        final int subIndex = getSubIndex(partitionIndex, index);

        // throws when index >= size()
        final List<E> subList = elements[partitionIndex];
        // throws when index is negative or last sublist is empty
        return subList.get(subIndex);
    }

    @Override
    public E set(final int index, final E element) {
        final int partitionIndex = getPartitionIndex(index);
        final int subIndex = getSubIndex(partitionIndex, index);

        // throws when index >= size()
        final List<E> subList = elements[partitionIndex];
        if (subIndex < 0 || subIndex >= subList.size()) {
            // a sublist may throw unsupported even when index OOB
            throw new IndexOutOfBoundsException();
        }
        return subList.set(subIndex, element);
    }

    @Override
    public Iterator<E> iterator() {
        // this may perform better with contained LinkedList
        return IterableUtils.chainedIterable(elements).iterator();
    }

    @Override
    public ListIterator<E> listIterator(final int index) {
        // indexOf, lastIndexOf, equals, removeRange, subList
        // call this method and for non-RandomAccess lists
        // the default implementation is slow
        // T O D O: implement LazyListIteratorChain similar to
        // org.apache.commons.collections4.iterators.LazyIteratorChain
        for (final List<E> subList : elements) {
            if (!(subList instanceof RandomAccess)) {
                throw new UnsupportedOperationException(
                    "Not RandomAccess: " + subList.getClass().getName());
            }
        }
        return super.listIterator(index);
    }

    /**
     * @return negative value when {@code index} is negative
     */
    private int getSubIndex(final int partitionIndex, final int index) {
        return index - (partitionIndex == 0 ? 0 : endIndexes[partitionIndex - 1]);
    }

    private int getPartitionIndex(final int index) {
        int location = Arrays.binarySearch(endIndexes, index);
        if (location < 0) {
            location = (~location) - 1;
        }
        return location + 1;
    }

    @Override
    public int size() {
        return endIndexes.length == 0 ? 0 : endIndexes[endIndexes.length - 1];
    }
}