ConcurrentModificationException в коде сортировки слиянием - PullRequest
1 голос
/ 21 февраля 2020

Я новичок в Java и вообще программирую. Я пытаюсь написать код сортировки слиянием для ArrayList класса, который я создал с именем Member, но код наталкивается на исключение ConcurrentModificationException. isLargerThan - это пользовательский метод, который я сделал для сравнения членов. Что я делаю не так?

  public static void mergeSort(List<Member> list) {
    List<Member> another1 = new ArrayList<Member>();
    another1 = list.subList(0, list.size() / 2);
    List<Member> another2 = new ArrayList<Member>();
    another2 = list.subList(list.size() / 2, list.size());
    if (another1.size() > 1) {
      mergeSort(another1);
    } if (another2.size() > 1) {
      mergeSort(another2);
    }
    merge(list, another1, another2);
  }

  public static void merge(List<Member> goal, List<Member> list1, List<Member> list2) {
    if (isLargerThan(list2.get(0), list1.get(0))) {
      goal = list1;
      goal.addAll(list2);
    } else {
      goal = list2;
      goal.addAll(list1);
    }
  }

РЕДАКТИРОВАТЬ:

С тех пор я изменил метод слияния на это:

  public static void merge(List<Member> goal, List<Member> list1, List<Member> list2) {
    if (isLargerThan(list2.get(0), list1.get(0))) {
      goal.clear();
      goal.addAll(list1);
      goal.addAll(list2);
    } else {
      goal.clear();
      goal.addAll(list2);
      goal.addAll(list1);
    }
  }

Ошибка теперь появляется в первой строке goal.addAll(list1);, где раньше она была в строке } if (another2.size() > 1) {.

1 Ответ

0 голосов
/ 21 февраля 2020

Подсписок не является фактическим списком, он просто сохраняет в нем ссылку на текущий список с начальным и конечным значением.

В связи с этим, goal, list1, list2 из merge функционал внутренне ссылается на тот же список.

Когда вы выполняете goal.addAll(list2); и goal.addAll(list1);, вы пытаетесь выполнить операцию чтения и записи в том же списке, вызывая ConcurrentModificationException.

Чтобы решить эту проблему, вы можете скопировать один список в другой вручную, а не использовать подсписок. Или создайте отдельный список, чтобы объединить результат.

...