SubList: примеры (JAVA)

Создание подпредставления списка с помощью subList
Раздел: Коллекции (Collection Framework) - List
subList(int fromIndex, int toIndex): List

Описание метода subList

Метод subList(int fromIndex, int toIndex) определён в интерфейсе List и возвращает представление (view) части исходного списка. Он позволяет работать с диапазоном элементов без создания новой копии, что экономит память и время. Изменения, внесённые в подсписок, отражаются на исходном списке, и наоборот.

Параметры:

  • fromIndex – начальный индекс включаемой части (включительно).
  • toIndex – конечный индекс исключаемой части (исключительно).

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

Исключения:

  • IndexOutOfBoundsException – если fromIndex меньше 0 или toIndex больше размера списка.
  • IllegalArgumentException – если fromIndex больше toIndex.

Метод применяется для извлечения подмножества элементов, для удаления диапазона через вызов clear() на подсписке, а также для выполнения операций над частью списка (сортировка, замена).

Примеры использования

Базовый пример – получение подсписка:

List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C", "D", "E"));
List<String> sub = list.subList(1, 4);
System.out.println(sub);
[B, C, D]

Изменение подсписка влияет на исходный список:

sub.set(0, "X");
System.out.println(list);
[A, X, C, D, E]

Удаление элементов через подсписок:

list.subList(2, 4).clear();
System.out.println(list);
[A, B, E]

Использование подсписка для сортировки диапазона:

List<Integer> nums = new ArrayList<>(Arrays.asList(5, 3, 1, 4, 2));
Collections.sort(nums.subList(1, 4));
System.out.println(nums);
[5, 1, 3, 4, 2]

Альтернативы в Java

В Java существуют другие способы получения части списка:

  • Stream API: list.stream().skip(from).limit(to - from).collect(Collectors.toList()) – создаёт новый независимый список, изменения не передаются исходному.
  • Копирование подсписка: new ArrayList<>(list.subList(from, to)) – создаёт независимую копию, но использует подсписок для копирования.
  • List.of(...).subList – для неизменяемых списков подсписок также неизменяем.

Когда предпочтительнее subList? Когда требуется работа с диапазоном как с представлением, особенно для изменения исходного списка через подсписок (например, удаление диапазона). Если нужна отдельная копия, лучше использовать Stream API или конструктор копии.

Аналоги в других языках

Python: срез списка list[1:4] возвращает новый список.

lst = ['A','B','C','D','E']
sub = lst[1:4]
print(sub)
['B', 'C', 'D']

JavaScript: метод slice().

let arr = ['A','B','C','D','E'];
let sub = arr.slice(1,4);
console.log(sub);
['B', 'C', 'D']

PHP: array_slice($list, 1, 3).

$list = ['A','B','C','D','E'];
$sub = array_slice($list, 1, 3);
print_r($sub);
Array ( [0] => B [1] => C [2] => D )

C#: метод GetRange().

List<string> list = new List<string>() { "A","B","C","D","E" };
List<string> sub = list.GetRange(1, 3);
Console.WriteLine(string.Join(", ", sub));
B, C, D

Kotlin: функция subList() аналогична Java.

Golang: срез слайса slice[1:4].

slice := []string{"A","B","C","D","E"}
sub := slice[1:4]
fmt.Println(sub)
[B C D]

Отличия от Java: в большинстве языков срез создаёт новый массив (копию), тогда как subList в Java – только представление. В Python и Go изменения в срезе не влияют на исходный, если только не используются ссылки на объекты. В PHP array_slice по умолчанию сбрасывает ключи.

Типичные ошибки

IndexOutOfBoundsException при неверных индексах:

list.subList(-1, 2);  // fromIndex < 0
list.subList(3, 2);   // fromIndex > toIndex
list.subList(0, 10);  // toIndex > size
Exception in thread "main" java.lang.IndexOutOfBoundsException

ConcurrentModificationException при структурном изменении исходного списка после создания подсписка:

List<String> sub = list.subList(1, 3);
list.add("F"); // структурная модификация
System.out.println(sub);
Exception in thread "main" java.util.ConcurrentModificationException

UnsupportedOperationException при попытке изменить подсписок неизменяемого списка (List.of):

List<String> immutable = List.of("A","B","C");
List<String> sub = immutable.subList(0, 2);
sub.add("X"); // попытка модификации
Exception in thread "main" java.lang.UnsupportedOperationException

Изменения в версиях Java

Метод subList существует с Java 1.2 и не претерпел значительных изменений. В Java 9+ для неизменяемых списков, созданных через List.of или List.copyOf, метод subList возвращает представление, но любые операции модификации (add, set, clear) приводят к UnsupportedOperationException. В Java 21 с введением интерфейса SequencedCollection поведение subList осталось прежним, однако теперь можно использовать методы reversed() для обратного обхода.

Расширенные примеры

Удаление диапазона элементов с помощью подсписка – эффективный способ очистить часть списка:

Пример java
List<String> list = new ArrayList<>(Arrays.asList("A","B","C","D","E"));
list.subList(1, 4).clear();
System.out.println(list);
[A, E]

Сортировка части списка – подсписок можно передать в Collections.sort:

Пример java
List<Integer> numbers = new ArrayList<>(Arrays.asList(3,1,4,2,5));
Collections.sort(numbers.subList(1, 4));
System.out.println(numbers);
[3, 1, 2, 4, 5]

Получение последних N элементов через вычисление индексов:

Пример java
int n = 3;
List<String> lastN = list.subList(Math.max(0, list.size() - n), list.size());
System.out.println(lastN);
[C, D, E] (если исходный список [A,B,C,D,E])

Использование с LinkedList – добавление элемента в подсписок изменяет исходный список:

Пример java
LinkedList<String> linked = new LinkedList<>(Arrays.asList("A","B","C","D","E"));
List<String> sub = linked.subList(1, 3);
sub.add("X"); // вставка в середину
System.out.println(linked);
[A, B, C, X, D, E]

Комбинирование со Stream API для обработки только части элементов:

Пример java
List<String> processed = list.subList(0, 3).stream()
    .map(String::toUpperCase)
    .collect(Collectors.toList());
System.out.println(processed);
[A, B, C]

Проверка производительности: subList не копирует данные, поэтому операции над ним выполняются быстро. Однако при работе с LinkedList доступ по индексу внутри подсписка может быть медленным (O(n)).

джава subList function comments

En
SubList Returns a view of the portion of this list between the specified fromIndex, inclusive, and toIndex, exclusive