简体   繁体   English

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

[英]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());

如何以优雅的方式使用 Java8 返回 map<object, long> 来自列表<object>计数发生?<div id="text_translate"><p> 我知道标题很拗口,所以我将尝试用一个例子来解释。</p><p> 我有一个清单。 Chores 有一个 id 字段作为标识符,但列表将包含许多家务,其中一些将具有相同的 ID。 我的目标是返回一个 Map&lt;Chore, Long&gt; ,其中 long 将计算杂务的出现次数。 例如:</p><pre> List&lt;Chore&gt; choreList = new ArrayList&lt;Chore&gt;(); choreList.add(new Chore("1", "vacuum", "7-6-22"); //Numbers 1,2,3 are the ID's for each chore choreList.add(new Chore("2", "dusting", "7-1-22"); choreList.add(new Chore("3", "mowing", "7-15-22"); choreList.add(new Chore("1", "vacuum", "7-14-22"); choreList.add(new Chore("1", "vacuum", "7-18-22"); choreList.add(new Chore("2", "dusting", "7-24-22");</pre><p> 使用此列表和 Java8 ZF7B44CFFAFD5C52223D5498196C8A2E7BZ function,我想返回一个 Map&lt;Chore, Long&gt;,其中包含家务 object 和事件。 因此,对于 ID 为“1”的杂项,长为 3。对于 ID 为“2”的杂项,长为 2……等等。</p><p> 我试图为此找到一个优雅的解决方案,但看起来每个人都可以得到如下内容:</p><pre> Map&lt;String, Long&gt; choresById = chores.stream().collect(Collectors.groupingBy(Chore::getId, Collectors.counting()));</pre><p> 我怎样才能想出 Map&lt;Chore, Long&gt; 而不是 Map&lt;String, Long&gt; (在这种情况下,字符串是 ID?)</p></div></object></object,> - How to use Java8 in an elegant way to return a map of <Object, Long> from a List<Object> counting occurrence?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 将迭代器上的当前对象移动到列表末尾 - Move current object on iterator to end of list 如何以优雅的方式使用 Java8 返回 map<object, long> 来自列表<object>计数发生?<div id="text_translate"><p> 我知道标题很拗口,所以我将尝试用一个例子来解释。</p><p> 我有一个清单。 Chores 有一个 id 字段作为标识符,但列表将包含许多家务,其中一些将具有相同的 ID。 我的目标是返回一个 Map&lt;Chore, Long&gt; ,其中 long 将计算杂务的出现次数。 例如:</p><pre> List&lt;Chore&gt; choreList = new ArrayList&lt;Chore&gt;(); choreList.add(new Chore("1", "vacuum", "7-6-22"); //Numbers 1,2,3 are the ID's for each chore choreList.add(new Chore("2", "dusting", "7-1-22"); choreList.add(new Chore("3", "mowing", "7-15-22"); choreList.add(new Chore("1", "vacuum", "7-14-22"); choreList.add(new Chore("1", "vacuum", "7-18-22"); choreList.add(new Chore("2", "dusting", "7-24-22");</pre><p> 使用此列表和 Java8 ZF7B44CFFAFD5C52223D5498196C8A2E7BZ function,我想返回一个 Map&lt;Chore, Long&gt;,其中包含家务 object 和事件。 因此,对于 ID 为“1”的杂项,长为 3。对于 ID 为“2”的杂项,长为 2……等等。</p><p> 我试图为此找到一个优雅的解决方案,但看起来每个人都可以得到如下内容:</p><pre> Map&lt;String, Long&gt; choresById = chores.stream().collect(Collectors.groupingBy(Chore::getId, Collectors.counting()));</pre><p> 我怎样才能想出 Map&lt;Chore, Long&gt; 而不是 Map&lt;String, Long&gt; (在这种情况下,字符串是 ID?)</p></div></object></object,> - How to use Java8 in an elegant way to return a map of <Object, Long> from a List<Object> counting occurrence? 有没有一种方法可以更优雅地编写此“ if”列表? - Is there a way to write this “if” list in a more elegant way? 是否有一种优雅的方式来转换List <Double> 进入清单 <Number> ? - Is there an elegant way to convert List<Double> into List<Number>? Hamcrest - 测试具有相同属性值的复杂对象的优雅方式 - Hamcrest - Elegant way to test complex object with samepropertyvaluesas 是否有一种优雅的方式来展开包装在2个嵌套的Optionals中的对象? - Is there an elegant way to unwrap an object wrapped in 2 nested Optionals? 用FilterInputStream对象读取大数据的一种优雅方法 - elegant way to read large data with FilterInputStream object 在Java中分配对象ID的优雅方式 - Elegant way to assign object id in Java 将 map 解析为 object 的优雅方法是什么? - What is the elegant way to parse a map into an object? 有没有更优雅的方法来基于列表启动线程? - Is there a more elegant way to launch a thread based on a list?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM