Не поврежден ли Collections.copy (в OpenJDK 6)? - PullRequest
3 голосов
/ 11 ноября 2009

Иногда я выгляжу совершенно неэффективно. Когда я почти закончил набирать это, мне удалось найти соответствующий отчет об ошибке в Sun. Я тогда хорошо подумал, может с таким же успехом опубликовать его, имея скриншот и все. Ответ следует.

Я знаю, "SELECT не сломан", и это всегда моя вина. Но здесь я действительно не понимаю, почему это должно быть. Мой фрагмент кода:

List<IGraphEdge> rgSrc = this._rgGetPath();
List<IGraphEdge> rgDst = new ArrayList<IGraphEdge>(rgSrc.size());
Collections.copy(rgDst, rgSrc);

Это выдает IndexOutOfBoundException с сообщением

java.lang.IndexOutOfBoundsException: Source does not fit in dest
        at java.util.Collections.copy(Collections.java:548)

В отладчике, когда я захожу в Collections.copy, два экземпляра ArrayList выглядят так:

Вид отладчика http://static.theuprightape.net/ql/img/debugger.png

Итак, в dest есть возможность удерживать этот элемент из src, хотя, естественно, size из dest по-прежнему равно 0, в конце концов, это то, что я хочу изменить, вызвав copy().

Глядя на исходный код реализации OpenJDK, становится понятно, почему выдается ошибка:

public static <T> void copy(List<? super T> dest, List<? extends T> src) {
    int srcSize = src.size();
    if (srcSize > dest.size())
        throw new IndexOutOfBoundsException("Source does not fit in dest");

Так скажите, пожалуйста, это ошибка или что я делаю не так?

Ответы [ 4 ]

4 голосов
/ 11 ноября 2009

Это не смотрит на емкость , это смотрит на размер. То есть пункт назначения должен содержать элементы, которые должны быть перезаписаны списком источников.

Я никогда не сталкивался с делом, где это было бы полезно. Обычно вам нужен конструктор копирования в одной из реализаций List или метод addAll интерфейса Collection.

2 голосов
/ 11 ноября 2009

Из документации к Collection.copy:

Копирует все элементы из одного список в другое. После операция, индекс каждого скопированного элемент в списке назначения будет быть идентичным его индексу в список источников. Список адресатов должен быть хотя бы до тех пор, пока источник список . Если это дольше, оставшиеся элементы в списке назначения незатронутыми.

Я согласен с вами, что это не очень интуитивно понятно, но кажется, что то, что вы действительно пытаетесь сделать, больше похоже на клон ().

2 голосов
/ 11 ноября 2009

Я не был первым, кто столкнулся с этим, но это всегда ваша вина. Согласно ответу на этот отчет об ошибке на Солнце, Collections.copy не предназначен для использования таким образом, вместо этого следует использовать List.appendAll().

Итак, я исправил свой код, чтобы он выглядел следующим образом:

List<IGraphEdge> rgSrc = this._rgGetPath();
List<IGraphEdge> rgDst = new ArrayList<IGraphEdge>(rgSrc.size());
rgDst.addAll(rgSrc);

Duh.

1 голос
/ 11 ноября 2009

Джавадоки говорят:

Броски: IndexOutOfBoundsException - если список получателей слишком мал для содержать весь список источников.

Так что, похоже, соответствует спецификации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...