【问题标题】:Insert items from one collection to another by condition and iterate over both collections using Google Guava or java 8 Stream API按条件将项目从一个集合插入另一个集合,并使用 Google Guava 或 java 8 Stream API 遍历两个集合
【发布时间】:2018-04-19 03:53:59
【问题描述】:

我有两个此类项目的特定案例:

public class Item {
    private Long id;
    private boolean isVisible;
}

列表 A 包含可见和不可见的项目。

列表 B 仅包含列表 A 中的可见项目,但排序(索引)不同。

我需要一个结果列表,其中可见项目按 B 的相对顺序放置,并且 A 中不可见项目的相对顺序保持不变。到目前为止,我能做到这一点的唯一方法是通过迭代器:

Iterator<Item> ai = A.listIterator();
Iterator<Item> bi = B.iterator();
while(ai.hasNext() && bi.hasNext()) {
    Item next = ai.next();
    if (next.isVisible() && B.contains(next)) {
        ai.set(bi.next())
    }
}

因此,我们将 B 中包含的 A 中的每个下一个可见项目替换为 B 中的项目。我想知道通过 Guava 或 Stream API 是否有更漂亮的解决方案。

【问题讨论】:

  • 对我来说似乎很干净。

标签: java collections java-8 java-stream guava


【解决方案1】:

实现一个比较器,检查这两个项目是否可见,因此两者都在 B 列表中。使用它们在 B 列表中的位置来确定排序顺序。如果其中一个不可见,则该订单应在 A 列表中。

class CustomSort implements Comparator<Item> {
    public int compare(Item i1, Item i2) {
        if (i1.isVisible() && i2.isVisible()) {
           return bi.indexOf(i1) - bi.indexOf(i2);
        }

        return ai.indexOf(i1) - ai.indexOf(i2);
    }
}

【讨论】:

    【解决方案2】:

    如果你需要在listA和listB之间共享同一个对象,那么你可以这样做

    遍历listA,
    - 如果 a 不可见,则返回 a,
    - 如果 a 可见,则返回 b。
    然后组合回一个列表并替换该列表(或根据需要创建一个新列表)。

        AtomicInteger index = new AtomicInteger();
        listA = listA.stream()
                .map(a -> a.isVisible ? listB.get(index.getAndIncrement()) :  a)
                .collect(Collectors.toList());
    

    【讨论】:

    • 正是我一直在寻找的。谢谢!
    • map() 函数不应该是有状态的。这将并行失败。
    【解决方案3】:

    假设资本 = 可见,小型股 = 不可见

    AList = { A, a, B, C, b, c, D, d, e }; //可见和不可见。
    BList = { C, D, B, A } ; //仅以不同的顺序可见。

    根据您的要求

    “因此,我们将 B 中包含的 A 中的每个下一个可见项目替换为 B 中的项目。我想知道通过 Guava 或 Stream API 是否有更漂亮的解决方案。”

    你希望结果是 ->

    CList = { C, a, D, B, b, c, A, d, e}; // 将 Visible 项按 B 的顺序排列

    您可以先过滤 A 的 Stream 以仅显示可见项目, 然后将该项目 ID 替换为 B 在该相对位置的值。 关键是使用AtomicInteger

            AtomicInteger index = new AtomicInteger();
            itemA.stream().filter(a -> a.isVisible)
                    .forEach(a -> {
                        a.id = itemB.get(index.getAndIncrement()).id;
                    });
    

    以下是完整代码:-

    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.atomic.AtomicInteger;
    import java.util.stream.IntStream;
    
    public class StreamExample {
    
        public static void main(String[] args) {
            List<Item> itemA = new ArrayList<>();
            List<Item> itemB = new ArrayList<>();
    
            itemA.add(new Item("A"));
            itemA.add(new Item("a", false));
            itemA.add(new Item("B"));
            itemA.add(new Item("C"));
            itemA.add(new Item("b", false));
            itemA.add(new Item("c", false));
            itemA.add(new Item("D"));
            itemA.add(new Item("e", false));
    
            itemB.add(new Item("C"));
            itemB.add(new Item("D"));
            itemB.add(new Item("B"));
            itemB.add(new Item("A"));
    
            System.out.println("BEFORE: ");
            System.out.println("A: ");
            itemA.forEach(System.out::print);
            System.out.println("\nB: ");
            itemB.forEach(System.out::print);
    
            AtomicInteger index = new AtomicInteger();
            itemA.stream().filter(a -> a.isVisible)
                    .forEach(a -> {
                        a.id = itemB.get(index.getAndIncrement()).id;
                    });
    
            System.out.println("\nAFTER: ");
            System.out.println("A: ");
            itemA.forEach(System.out::print);
    
    
        }
    }
    
    
    class Item {
        String id;
        boolean isVisible = true;
    
        public Item(String id) {
            this.id = id;
        }
    
        public Item(String id, boolean isVisible) {
            this.id = id;
            this.isVisible = isVisible;
        }
    
        @Override
        public String toString() {
            return " {'" + id + '\'' +
                    '}';
        }
    }
    

    以下是输出

    BEFORE: 
    A: 
     {'A'} {'a'} {'B'} {'C'} {'b'} {'c'} {'D'} {'e'}
    B: 
     {'C'} {'D'} {'B'} {'A'}
    AFTER: 
    A: 
     {'C'} {'a'} {'D'} {'B'} {'b'} {'c'} {'A'} {'e'}
    

    【讨论】:

    • 不过,这并不是我想要的。我需要替换项​​目本身,而不是重置它的 ID。我想,下面的 Angel Koh 的例子可以满足我的需要。还是谢谢你的回答!
    猜你喜欢
    • 2015-10-20
    • 2014-11-27
    • 1970-01-01
    • 1970-01-01
    • 2016-02-28
    • 1970-01-01
    • 1970-01-01
    • 2021-02-01
    • 2021-11-21
    相关资源
    最近更新 更多