2015-06-09 3 views
7

Учитывая список целочисленных элементов, как получить максимальное значение и его индекс за один снимок. Если имеется более одного элемента с таким же максимальным значением, возвращающий индекс любого из них является точным.Как получить индекс и максимальное значение массива за один снимок?

Например:

// Initialize list of integer 
    List<Integer> intList = Arrays.asList(5, 8, 3, 2); 
    // To get max value 
    Optional<Integer> maxVal = intList.stream().reduce(Integer::max); 
    // But how could I also get its index without iterating the array again? 

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

ответ

8

Как правило, если вам нужен индекс, вам придется перетекать через индексы. Тогда задача становится прямолинейно:

List<Integer> intArr = Arrays.asList(5, 8, 3, 2); 
IntStream.range(0, intArr.size()) 
    .reduce((a,b)->intArr.get(a)<intArr.get(b)? b: a) 
    .ifPresent(ix->System.out.println("Index "+ix+", value "+intArr.get(ix))); 

более элегантным решением, которое, к сожалению, включает в себя бокс накладного расходов является

IntStream.range(0, intArr.size()) 
    .boxed().max(Comparator.comparing(intArr::get)) 
    .ifPresent(ix->System.out.println("Index "+ix+", value "+intArr.get(ix))); 
+0

Что значение в штучной упаковке? –

+1

@SriniK Я считаю, что это потому, что у вас не может быть «Компаратор ». Но опять же, я могу ошибаться, так как я все еще немного новичок в Java 8. – CKing

+3

@Chetan Kinger: вы правы, нет «Компаратор », и поэтому 'IntStream' не предлагает' max (Comparator) ', но только' max() ', который здесь не помогает (то же самое относится к' min' или 'sorted',' IntStream' поддерживает только натуральный порядок). – Holger

1

Если вы не возражаете против использования стороннего кода, моя StreamEx библиотеки предоставляет некоторые сочетания клавиш для выполнения этой задачи:

List<Integer> intArr = Arrays.asList(5, 8, 3, 2); 
IntStreamEx.ofIndices(intArr) 
      .maxBy(intArr::get) 
      .ifPresent(ix->System.out.println("Index "+ix+", value "+intArr.get(ix))); 

Внутренне это близко к первому раствору, предоставленного @Holger (без бокса).

1

В java8 вы можете execute streams in parallel

Integer[] intArr= {1,2,6,2,234,3,54,6,4564,456}; 

IntStream.range(0, intArr.length-1).parallel(). 
       reduce((a,b)->intArr[a]<intArr[b]? b: a). 
       ifPresent(ix -> System.out.println("Index: " + ix + ", value: " + intArr[ix])); 
0

Я не думаю, что в настоящее время любое решение, которое столь же быстро, как вручную итерации:

int maxValueIndex = 0; 
Integer maxValue = null; 
for (int i = 0, n = intList.size(); i < n; ++i) { 
    Integer value = intList.get(i); 
    if (value == null || maxValue != null && value <= maxValue) 
     continue; 
    maxValue = value; 
    maxValueIndex = i; 
}