简体   繁体   English

如何在自定义中实现subList() ArrayList

[英]How to implement subList() in Custom ArrayList

I'm implementing my own generic ArrayList and everything is fine, but I've got a problem with the last method - List subList(int fromIndex, int toIndex).我正在实现我自己的通用 ArrayList,一切都很好,但我对最后一个方法有问题 - List subList(int fromIndex, int toIndex)。 I've tried to implement it, but still, I only create a copy of my main list and modify only it.我已经尝试实现它,但我仍然只创建了主列表的副本并仅对其进行了修改。 My current code is我目前的代码是

public List<T> subList(int fromIndex, int toIndex) {
        if (fromIndex < 0 || toIndex > size() || fromIndex > toIndex)
            throw new IndexOutOfBoundsException();
        Object subarray[] = new Object[toIndex - fromIndex];
        for (int i = 0; i < subarray.length; i++) {
            subarray[i] = array[fromIndex + i];
        }
        List<T> subList = Arrays.asList((T) subarray);
    return subList;
}

I've also tried to do it using ArrayList instead of an array, but it still doesn't work (modify only my new subList instead of the whole list).我也尝试使用 ArrayList 而不是数组来完成它,但它仍然不起作用(只修改我的新子列表而不是整个列表)。 How can I repair it?我该如何修复它? Do I have to implement another class?我必须实施另一个 class 吗?

EDIT I also add my test method, I still get failure (the value in main list isn't changed)编辑我也添加了我的测试方法,我仍然失败(主列表中的值没有改变)

@Test
    void subListWithoutNulls() {
        CustomArrayList<Integer> array = new CustomArrayList<>();
        array.add(3);
        array.add(7);
        array.add(2);
        array.add(5);
        array.add(8);
        array.add(3);
        array.subList(1, 4).set(0, 12);
        assertEquals(12, array.get(1));
    }

If you derive from AbstractList , an implementation will be provided for you: https://docs.oracle.com/javase/7/docs/api/java/util/AbstractList.html#subList(int,%20int)如果您从AbstractList派生,将为您提供一个实现: https://docs.oracle.com/javase/7/docs/api/java/util/AbstractList.html#subList(int,%20int)

Otherwise you will have to write a new class that properly delegates everything to the original list.否则,您将不得不编写一个新的 class 来正确地将所有内容委托给原始列表。

Assuming you are doing this is a learning exercise, here's one way to create a sublist that has pass-through behaviour.假设您这样做是一种学习练习,下面是创建具有传递行为的子列表的一种方法。 It involves making an implementation of the List interface.它涉及实现List接口。 Just about every method implementation is specifically to cater to the idea of a sublist.几乎每个方法的实现都是专门为了迎合子列表的想法。 As the specs say, you don't have to consider the case of structural changes made to the underlying list (eg what if in between making a subList and eg calling size() on that subList, someone invokes .clear() on the top-level list? Does that mean the sublist should now return 0? You get to define what happens yourself, as per the spec of java.util.List .正如规范所说,您不必考虑对基础列表进行结构更改的情况(例如,如果在创建子列表和在该子列表上调用 size() 之间,有人在顶部调用.clear() -level 列表?这是否意味着子列表现在应该返回 0?您可以根据java.util.List的规范自行定义会发生什么。

public List<T> subList(int fromIndex, int toIndex) {
  if (fromIndex < 0) throw new IndexOutOfBoundsException("fromIndex is below 0");
  if (toIndex > size()) throw new IndexOutOfBoundsException("toIndex is above 'size'");
  if (toIndex < fromIndex) throw new IndexOutOfBoundsException("toIndex is before fromIndex");

  return new List<T>() {
    public void size() {
      return toIndex - fromIndex;
    }

    public void get(int idx) {
      return MyList.this.get(idx + fromIndex);
    }

    public boolean add(T elem) {
      return MyList.this.add(toIndex++, elem);
    }

    // and so on.
  };
}

Take a look at that impl of the add method (which makes the assumption that the underlying add method always returns true - if your list impl doesn't, do not increment toIndex unless true is returned): It can be a tad complicated.看一下add方法的 impl(它假设底层add方法总是返回 true - 如果你的列表 impl 不返回 true,则不要递增 toIndex 除非返回 true):它可能有点复杂。 Here, adding an item to the subList means the subList is now one larger than it was.在这里,向 subList 添加一个项目意味着 subList 现在比原来大了一个。 For that matter, so is the underlying list.就此而言,基础列表也是如此。 Also an add-to-the-end operation on a subList doesn't neccesarily mean that you're adding to the end of the underlying list, so you'd invoke the add-in-the-middle version.此外,对 subList 的添加到末尾操作并不一定意味着您要添加到基础列表的末尾,因此您将调用中间添加版本。 Outer.this.method() is java-ese for invoking a method from your outer class, which we need here, as both the inner class and the outer class have very similar methods, so we need to be clear when we invoke eg add(idx, elem) - is that invoking the subList's add method, or the underlying (outer class's) add method? Outer.this.method()是java-ese,用于调用外部class的方法,我们在这里需要它,因为内部class和外部class的方法非常相似,因此我们在调用时需要清楚 eg add(idx, elem) - 是调用子列表的添加方法,还是底层(外部类的)添加方法? Outer.this.x can be used to make that clear (if you don't do that, you get the inner list, and thus most likely a boatload of StackOverflowErrors if you try it). Outer.this.x可以用来说明这一点(如果你不这样做,你会得到内部列表,因此如果你尝试它很可能会出现大量 StackOverflowErrors)。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM