按条件将项目从一个集合插入到另一个集合,并使用 Google Guava 或 java 8 Stream API 遍历两个集合
Insert items from one collection to another by condition and iterate over both collections using Google Guava or java 8 Stream API
我有两个此类项目的特定案例:
public class Item {
private Long id;
private boolean isVisible;
}
列表 A 包含可见和不可见的项目。
列表 B 仅包含列表 A 中的可见项,但排序(索引)不同。
我需要一个结果列表,其中可见项目按 B 的相对顺序放置,并且不可见项目的相对顺序保持不变。到目前为止,我唯一能做对的方法是通过迭代器:
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.
实现一个比较器来检查两个项目是否可见,因此它们都在 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);
}
}
假设资本 = VISIBLE,小型股 = INVISIBLE
AList = { A, a, B, C, b, c, D, d, e }; //both Visible & Invisible.
BList = { C, D, B, A } ; //only Visible with different order.
根据您的要求
"So we're replacing every next visible item in A contained in B, with item from B. I wonder if there is more beautiful solution to this problem through either Guava or Stream API."
你想要的结果是 ->
CList = { C, a, D, B, b, c, A, d, e}; // resort the Visible items to B's order
您可以先过滤 A 的 Stream 以仅显示可见项目,
然后在该相对位置用 B 的值替换该项目 ID。
关键是使用 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'}
如果你需要在listA和listB之间共享同一个对象,那么你可以这样做
遍历listA,
- 如果 a 不可见,return a,
- 如果 a 可见,return b.
然后组合回列表并替换列表(或根据需要创建新列表)。
AtomicInteger index = new AtomicInteger();
listA = listA.stream()
.map(a -> a.isVisible ? listB.get(index.getAndIncrement()) : a)
.collect(Collectors.toList());
我有两个此类项目的特定案例:
public class Item {
private Long id;
private boolean isVisible;
}
列表 A 包含可见和不可见的项目。
列表 B 仅包含列表 A 中的可见项,但排序(索引)不同。
我需要一个结果列表,其中可见项目按 B 的相对顺序放置,并且不可见项目的相对顺序保持不变。到目前为止,我唯一能做对的方法是通过迭代器:
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.
实现一个比较器来检查两个项目是否可见,因此它们都在 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);
}
}
假设资本 = VISIBLE,小型股 = INVISIBLE
AList = { A, a, B, C, b, c, D, d, e }; //both Visible & Invisible.
BList = { C, D, B, A } ; //only Visible with different order.
根据您的要求
"So we're replacing every next visible item in A contained in B, with item from B. I wonder if there is more beautiful solution to this problem through either Guava or Stream API."
你想要的结果是 ->
CList = { C, a, D, B, b, c, A, d, e}; // resort the Visible items to B's order
您可以先过滤 A 的 Stream 以仅显示可见项目, 然后在该相对位置用 B 的值替换该项目 ID。 关键是使用 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'}
如果你需要在listA和listB之间共享同一个对象,那么你可以这样做
遍历listA,
- 如果 a 不可见,return a,
- 如果 a 可见,return b.
然后组合回列表并替换列表(或根据需要创建新列表)。
AtomicInteger index = new AtomicInteger();
listA = listA.stream()
.map(a -> a.isVisible ? listB.get(index.getAndIncrement()) : a)
.collect(Collectors.toList());