有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

串联列表的java列表视图

我想创建一个列表视图,该视图由许多其他列表串联而成

例如:

List<Integer> l1 = Lists.newArrayList(1);
List<Integer> l2 = Lists.newArrayList(2);
List<Integer> l3 = Lists.newArrayList(3);

// This call should not copy any of the argument lists content
List<Integer> concatenation = new ConcatenationListView(l1, l2, l3);

System.out.println(concatenation); // Prints [1, 2, 3]
l3.add(4);
System.out.println(concatenation); // Prints [1, 2, 3, 4]

我可以在Java中使用什么样的技术和/或模式来满足这些需求

详细信息

  • 我希望连接是懒惰的。(这就是本文中“视图”的含义。)
  • 我希望更改组件列表,以反映连接。(也是“视图”的含义)
  • 视图不需要是可修改的
  • 这与^{}方法有点相反
  • 它类似于Guava^{}方法,但我需要一个列表作为结果,而不是一个iterable
  • 我的问题类似于this one,但我需要一个List作为结果连接,其中另一个问题的海报满足于一个Iterable作为结果

共 (3) 个答案

  1. # 1 楼答案

    你可以用Java8 Stream-API来做这个

    Stream.of(l1, l2, l3)
        .flatMap(List::stream)
        .forEach(System.out::println);
    

    这将创建一个由三个列表组成的流,然后通过将每个列表转换为流本身(List::stream)并将它们放在一起,将每个列表中的所有项目连接在一起。毕竟,它输出控制台上的每个元素

    另外:默认情况下,流是惰性的,这意味着

    computation on the source data is only performed when the terminal operation is initiated, and source elements are consumed only as needed.

    Source

  2. # 2 楼答案

    下面是一个类的实现,该类充当多个列表串联的视图

    这不需要太多的台词:

    /**
     * A list which acts as view of the concatenation of a number of lists.
     */
    public class ListConcatenationView<E> extends AbstractList<E> {
        private final List<E>[] lists;
    
        @SafeVarargs
        public ListConcatenationView(List<E>... lists) {
            this.lists = lists;
        }
    
        @Override
        public E get(int ix) {
            int localIx = ix;
            for (List<E> l : lists) {
                if (localIx < 0) throw new IndexOutOfBoundsException(ix); 
                if (localIx < l.size()) return l.get(localIx);
                localIx -= l.size();
            }
            return null;
        }
    
        @Override
        public int size() {
            int size = 0;
            for (List<E> l : lists) {
                size += l.size();
            }
            return size;
        }
    }
    
  3. # 3 楼答案

    Java类库没有这样的组合类,所以您需要自己编写

    由于您希望该类允许修改基础列表,因此没有比O(L)更好的效率,O(L)中L是视图管理的列表数,因为索引转换需要您在每次需要读取或插入特定索引时遍历列表

    另一方面,这使得实现非常简单-转换索引的代码如下所示:

    class ListView : List<T> {
        private List<List<T>> lists = ...
        public T get(int index) {
            int i = 0;
            while (i != lists.size() && index > lists.get(i).size()) {
                index -= lists.get(i++).size();
            }
            if (i == lists.size()) {
                throw new IndexOutOfBoundsException();
            }
            return lists.get(i).get(index);
        }
        ...
    }