将对象移动到列表末尾的优雅方式

kar*_*kar 5 java java-8

如果一个对象的布尔标志设置为 true,我试图将它移动到列表的末尾。以下是我采用删除它并重新添加它的方法。在 Java 8 中是否有更好更优雅的方法来做到这一点?我必须使用该布尔标志来确定对象是否需要转到列表末尾。请指教。

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 +
                '}';
    }
}
Run Code Online (Sandbox Code Playgroud)

use*_*ser 3

我觉得这比对整个列表进行排序更有效,因为ArrayLists 的时间复杂度为 O(n)。

您可以找到与该谓词匹配的所有对象,并以此移动到末尾。ArrayList使用索引而不是对象本身调用删除方法,这样如果列表是 an而不是 a ,则不必再次在内部遍历它LinkedList。正如霍尔格指出的那样,第一个更简洁,但对于多个对象来说效率相当低。

IntStream.range(0, list.size())
    .filter(i -> list.get(i).isMoveToLast())
    .foreach(i -> list.add(list.remove(i)));
Run Code Online (Sandbox Code Playgroud)

另一种方法效率更高,但需要 2 行而不是 1 行:

List<Item> newList = new ArrayList<>(list.size());
newList.addAll(
    list.stream()
         .filter(it -> it.isMoveToLast() || !newList.add(it))
         .collect(Collectors.toList()));
Run Code Online (Sandbox Code Playgroud)

如果您只想将单个对象移动到末尾,您也可以这样做

IntStream.range(0, list.size())
    .filter(i -> list.get(i).isMoveToLast())
    .findFirst()
    .ifPresent(i -> list.add(list.remove(i)));
Run Code Online (Sandbox Code Playgroud)

如果它找到了它正在寻找的对象,这将短路并且不会遍历整个列表。

对于a,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);
Run Code Online (Sandbox Code Playgroud)

  • 对于单个元素,在“ArrayList”上执行“list.add(list.remove(i))”的时间复杂度为 O(n)。当您必须对列表中未知数量的元素执行该操作时,您可能需要重复执行*n*次,这使得整个操作为 O(n²),这比排序要差得多。 (3认同)