[英]Elegant way to move Object to end of list
I am trying to move an object to the end of the list if it has a boolean flag set to true.如果 boolean 标志设置为 true,我正在尝试将 object 移动到列表的末尾。 The following works where I am taking the route of deleting it and adding it back.以下工作我正在采取删除它并将其添加回来的路线。 Is there a better more elegant way to do this in Java 8?在 Java 8 中有更好更优雅的方法吗? I have to work with that boolean flag to identify if object needs to go to end of list.我必须使用 boolean 标志来确定 object 是否需要 go 到列表末尾。 Please advice.请指教。
public class Main {
public static void main(String[] args) {
Item item1 = new Item();
item1.setName("item1");
Item item2 = new Item();
item2.setName("item2");
item2.setMoveToLast(true);
Item item3 = new Item();
item3.setName("item3");
Item item4 = new Item();
item4.setName("item4");
List<Item> items = new ArrayList<>(Arrays.asList(item1, item2, item3, item4));
System.out.println("Before moving...");
items.forEach(System.out::println);
// only item2 has flag set to true thus only item2 will be sent to end of list.
move(items);
System.out.println("After moving...");
items.forEach(System.out::println);
}
private static void move(List<Item> items){
for (int i = 0; i < items.size(); i++) {
Item item = items.get(i);
if (item.isMoveToLast()){
items.remove(item);
items.add(item);
}
}
}
}
@Getter
@Setter
class Item {
private int order;
private String name;
private boolean isMoveToLast;
@Override
public String toString() {
return "Item{" +
"name='" + name + '\'' +
", isMoveToLast=" + isMoveToLast +
'}';
}
}
This is not elegant:这并不优雅:
Map<Boolean,List<Item>> partitionBy = items.stream()
.collect(Collectors.partitioningBy(Item::isMoveToLast));
Stream.of(partitionBy.get(false),partitionBy.get(true)).flatMap(List::stream)
.collect(Collectors.toList());
Or based on @Holger 's comment:或基于@Holger的评论:
Stream.concat(partitionBy.get(false).stream(), partitionBy.get(true).stream())
.collect(Collectors.toList());
I feel this is more efficient than sorting the entire list because it's O(n) for ArrayList
s.我觉得这比对整个列表进行排序更有效,因为它是 O(n) 对于ArrayList
s。
You can find all objects matching that predicate and move to the end with this.您可以找到与该谓词匹配的所有对象并以此移动到最后。 The remove method's called with the index instead of the object itself so that the list does not have to go through it internally again if it's an ArrayList
and not a LinkedList
.使用索引而不是 object 本身调用 remove 方法,因此如果列表是ArrayList
而不是LinkedList
,则列表不必在内部再次通过它 go。 This first one is more concise but pretty inefficient with multiple objects, as Holger pointed out.正如 Holger 指出的那样,第一个更简洁,但对于多个对象来说效率很低。
IntStream.range(0, list.size())
.filter(i -> list.get(i).isMoveToLast())
.foreach(i -> list.add(list.remove(i)));
Another way to do it that's a bit more efficient but takes 2 lines instead of 1:另一种更高效但需要 2 行而不是 1 行的方法:
List<Item> newList = new ArrayList<>(list.size());
newList.addAll(
list.stream()
.filter(it -> it.isMoveToLast() || !newList.add(it))
.collect(Collectors.toList()));
If you only want to move a single object to the end, you can also do如果只想将单个 object 移到最后,也可以这样做
IntStream.range(0, list.size())
.filter(i -> list.get(i).isMoveToLast())
.findFirst()
.ifPresent(i -> list.add(list.remove(i)));
This will short-circuit and not go through the entire list if it finds the object it's looking for.如果它找到它正在寻找的 object,这将在整个列表中短路而不是 go。
For a LinkedList
you could do this, but it doesn't require Java 8:对于LinkedList
,您可以这样做,但不需要 Java 8:
Iterator<Item> iter = list.iterator();
List<Item> toAdd = new ArrayList<>();
while (iter.hasNext()) if (iter.next().isMoveToLast()) toAdd.add(iter.remove());
for (Item it : toAdd) list.add(it);
To answer the question of moving an element to the end of the list, I think the most elegant way is to do a rotate on a sublist.要回答将元素移动到列表末尾的问题,我认为最优雅的方法是对子列表进行旋转。 In your case this can be done like this:在您的情况下,可以这样做:
Collections.rotate(items.subList(i, items.size()), -1);
You could sort is with stream您可以使用 stream 进行排序
List<Item> items = new ArrayList<>(Arrays.asList(item1, item2, item3, item4));
items = items.stream()
.sorted((i1,i2) -> Boolean.compare(i1.isMoveToLast(),i2.isMoveToLast()))
.collect(Collectors.toList());
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.