2015-10-25 4 views
2

Возможно ли создать подсписку из другого списка, используя только индексы элементов? Я ищу хорошее решение, например. лямбды, потоки от Java 8.Создание подписок из индексов

Например (псевдокод):

a = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] 
b = a.getByIndices([0, 2, 4, 5, 3]) 
print(b) // [10, 8, 6, 5, 7] 
+0

Конечно, это возможно *. Я могу подумать, как это сделать с помощью цикла for, но мне нечего сказать о потоках. – Nayuki

+5

Вы что-то пробовали? – RealSkeptic

+0

@RealSkeptic: Я думал об использовании фильтра, но тогда мне нужно вызвать indexOf и проверить, указан ли индекс в списке индексов. Я думаю, что это не эффективное решение. – dragon7

ответ

7

Вы могли бы иметь следующий метод:

private static <T> List<T> getByIndices(List<T> list, List<Integer> indexes) { 
    return indexes.stream().map(list::get).collect(toList()); 
} 

Это создает Stream из данных показателей, карты в элемент списка в индексе и собрать результат в список.

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

List<Integer> list = Arrays.asList(10, 9, 8, 7, 6, 5, 4, 3, 2, 1); 
List<Integer> indexes = Arrays.asList(0, 2, 4, 5, 3); 
System.out.println(getByIndices(list, indexes)); // prints [10, 8, 7, 6, 5] 
6

Для массивов Интс вы могли бы использовать это:

int[] b = IntStream.of(0, 2, 4, 5, 3) 
     .map(i -> a[i]) 
     .toArray(); 
+1

За исключением того, что он не компилируется, поскольку в классе 'Arrays' нет версии varargs ... Вместо этого вам нужно использовать' IntStream.of'. –

+1

@TagirValeev Спасибо за исправление! – assylias

1

Расширение AbstractList быстрый способ получить список реализации и работает. Как и обычный метод List.subList, следующий список подкрепляется главным списком, поэтому изменения в подсписке будут записываться в основной список (который может быть или не быть желаемой функцией, но вы всегда можете создать новый отдельный ArrayList из подписок, если необходимо). Удаление элемента через подсписку не выполняется; это было бы выполнимо, но потребовало бы немного больше работы.

public static <E> List<E> sublistFromIndices(List<E> list, int... indices) { 
    Objects.requireNonNull(list); 
    Objects.requireNonNull(indices); 
    return new AbstractList<E>() { 
     @Override 
     public int size() { 
      return indices.length; 
     } 

     @Override 
     public E get(int index) { 
      return list.get(indices[index]); 
     } 

     @Override 
     public E set(int index, E element) { 
      return list.set(indices[index], element); 
     } 
    }; 
} 
0

Я написал эту функцию, которая делает то, что вы просите. Я не могу понять, как сделать его лямбда-функцией, но я буду продолжать работать над этим.

public static <E> void createSublist(List<E> oldList, List<E> newList, int[] indicies){ 
     for(int i = 0; i < indicies.length; i++) 
      newList.add(oldList.get(indicies[i]));} //Adds indicies to new list 
Смежные вопросы