【问题标题】:How to calculate the element total change times in an ArrayList如何计算 ArrayList 中的元素总更改时间
【发布时间】:2021-03-30 07:52:04
【问题描述】:

场景是我有一个类如下,

@Data
class Operation
{
    private String id;
    private String name;
    private String description;
}

还有一个包含大量 Operation 实例的 ArrayList。

例如,ArrayList 中有五个实例,

{"id":"0001", "name":"up"}
{"id":"0002", "name":"down"}
{"id":"0003", "name":"left"}
{"id":"0004", "name":"left"}
{"id":"0005", "name":"up"}

想知道这个名字在ArrayList中改变了多少次,这种情况下,第二个名字是down的,和第一个不一样,改变次数是1,第三个名字也和第二个不一样name,那么变化次数是2,但是第四个名字和第三个一样,所以变化次数还是2,第五个和第四个不同,所以这个ArrayList的变化次数是3。

有没有不遍历ArrayList的方法来计算?

【问题讨论】:

  • 也许在填充 ArrayList 时有一种计数方法,但如果不遍历 ArrayList,就没有办法做到这一点。
  • 您可以遍历列表并继续检查当前名称值与以前的名称,这需要 O(n) 时间,这在许多情况下会更好。但是,如果不遍历列表,这将是困难的(或者是不可能的)
  • 相关:Count the number of times values change in a series(我知道它是 Python,但我发誓大多数想法也可以在 Java 中使用)。请搜索更多。

标签: java list algorithm arraylist


【解决方案1】:
    List<Operation> operations = List.of(
            new Operation("0001", "up"),
            new Operation("0002", "down"),
            new Operation("0003", "left"),
            new Operation("0004", "left"),
            new Operation("0005", "up"));
    
    // Don’t include index 0 since it has no previous name to compare with
    long numberOfNameChanges = IntStream.range(1, operations.size())
            .filter(i -> ! operations.get(i - 1).getName()
                    .equals(operations.get(i).getName()))
            .count();
    
    System.out.println("Count is " + numberOfNameChanges);

输出是:

计数是 3

它确实遍历了列表。

为了一个完整的例子,我使用了List.of()(从Java 9 开始)而不是ArrayList,但是流操作也可以与ArrayList 一样工作。

我通常说当涉及更多列表元素的操作时,流操作效果不佳。这似乎是个例外;我自己发现流解决方案很好。如果您愿意,也可以使用循环对其进行编码。

PS 我不太喜欢在你没有付出那么多努力的时候放弃工作代码。只有我发现这用代码更容易解​​释,所以我妥协了。

编辑

我们收集一组值怎么样……

不,这行不通。我举两个例子给你看。第一个更简单,我刚刚从您的列表中删除了最后一个 up,因此只有 2 个值更改:

    List<Operation> operations = List.of(
            new Operation("0001", "up"),
            new Operation("0002", "down"),
            new Operation("0003", "left"),
            new Operation("0004", "left"));
    
    Set<String> collect = operations.stream()
            .map(operation -> operation.name.toLowerCase())
            .collect(Collectors.toSet());
    
    System.out.println(collect);

[左、上、下]

即使我删除了一个值更改,集合中仍然有 3 个元素。你可能认为你可以只减去 1。不是这样。看下一个也是最后一个例子:

    List<Operation> operations = List.of(
            new Operation("0001", "up"),
            new Operation("0003", "left"),
            new Operation("0002", "up"),
            new Operation("0003", "left"),
            new Operation("0004", "left"));

现在有三个值变化,但集合中只有两个元素:

[左,上]

如果你减去 1,你最终会得到 1。

您现在可能已经意识到,Set 方法的问题是它没有考虑到稍后再次出现相同名称时会导致新的值更改。

【讨论】:

  • 嗨 Ole,我正在关注您的回答,我们收集一组值怎么样,例如 Set&lt;String&gt; collect = operations.stream() .map(operation -&gt; operation.name.toLowerCase()) .collect(Collectors.toSet());
  • 抱歉,@silentsudo,这行不通。这听起来是一个不错且简单的想法。查看我的编辑。
【解决方案2】:

有没有不遍历ArrayList的方法来计算?

没有。

要查看列表中的每个值,并与相邻的值进行比较,需要遍历列表。没有神奇的捷径。

【讨论】:

    【解决方案3】:

    当您使用 if(setEvent(index,object)) 例如,您可以从该事件中制作 if(object == "meow) return true; return false; 如果为真则设置,否则不设置。

    您可以使用抽象类来添加事件(监听器)

    public abstract class MyList<Object> {
    
    private ArrayList<Object> list = new ArrayList<>();
    
    public void set(int index,Object object){
        if(setEvent(index,object)) list.set(index,object);
    }
    
    public void add(Object object){
        if(addEvent(object)) list.add(object);
    }
    
    public void remove(Object object){
        if(removeEvent(object)) list.remove(object);
    }
    
    public void remove(int index){
        if(removeEvent(index)) list.remove(index);
    }
    
    public Object get(int index){
        if(getEvent(index)) return list.get(index);
        return null;
    }
    
    public void clear(){
        if(clearEvent()) list.clear();
    }
    
    //Abstract
    
    public abstract boolean setEvent(int index, Object object);
    
    public abstract boolean addEvent(Object object);
    
    public abstract boolean removeEvent(Object object);
    
    public abstract boolean removeEvent(int index);
    
    public abstract boolean getEvent(int index);
    
    public abstract boolean clearEvent();
    
    }   
    

    【讨论】:

    • 首先,这个解决方案有什么价值?你能用文字解释一下吗?为什么要使用 Object,为什么不使用通用解决方案呢?
    猜你喜欢
    • 1970-01-01
    • 2017-11-06
    • 2016-08-30
    • 2021-04-07
    • 1970-01-01
    • 1970-01-01
    • 2012-09-28
    • 2022-01-03
    • 1970-01-01
    相关资源
    最近更新 更多