Получить max и maxIndex суммы двух списков с плавающей точкой в ​​Java быстро - PullRequest
1 голос
/ 03 апреля 2019

Я пытаюсь вычислить пару максимальных сумм из двух списков более быстрым способом, чем то, что я описал ниже, используя "легкие потоки" :

 List<Float> pairsSum = new ArrayList<>();
 // Get the list with all the sums
 Stream.range(0, list1.size())
          .forEach(i -> pairsSum.add(list1.get(i) + list2.get(i)));
 // Get the index of the max pair
 maxIndex = pairsSum.indexOf(Stream.of(pairsSum).max(Double::compare).orElse(0f));

Ответы [ 3 ]

3 голосов
/ 03 апреля 2019
List<Float> pairsSum = new ArrayList<>(repLeftForces.size());
// Get the list with all the sums
int maxIndex = -1;
float max = 0F;
for (int i =0; i < repLeftForces.size(); ++i) {
    float sum = list1.get(i) + list2.get(i);
    //pairsSum.add(sub);
    if (maxIndex == -1 || sum > max) {
        maxIndex = i;
        max = sum;
    }
 }

Список парных сумм на самом деле не нужен. Но при использовании фактический размер известен заранее.

Поскольку кто-то хочет сделать , тоже уменьшить для максимума и дополнительно получить maxIndex, лучше всего использовать классический цикл вместо использования Stream.

2 голосов
/ 03 апреля 2019

Краткое решение заключается в использовании метода IntStream и reduce():

int maxIndex = IntStream.range(0, list1.size())
        .reduce((i1, i2) -> list1.get(i1) + list2.get(i1) < list1.get(i2) + list2.get(i2) ? i2 : i1)
        .orElse(-1);

Если вам нужен индекс, и значения, и сумма, вы можете использовать пользовательский класс Result:

public static class Result {
    private int index;
    private float left;
    private float right;
    private float sum;
    // constructor and getters
}

Используйте это так:

Result max = IntStream.range(0, list1.size())
        .mapToObj(i -> new Result(i, list1.get(i), list2.get(i), list1.get(i) + list2.get(i)))
        .max(Comparator.comparing(Result::getSum))
        .orElse(null);

Сложность времени в обоих случаях составляет O (n) .

1 голос
/ 03 апреля 2019

Вы можете создать список сумм в одной строке, сопоставляя потоки (я добавил добавление разрывов строк для удобочитаемости):

    //made some example lists
    List<Float> list1 = Arrays.asList(new Float[]{1F, 2F, 3F});
    List<Float> list2 = Arrays.asList(new Float[]{2F, 3F, 4F});

    // Get the list with all the sums
    List<Float> sums = list1.stream()
            .map( f -> (list2.get(list1.lastIndexOf(f)) + f ) )
            .collect(Collectors.toList());

    // Get the index of the max pair
    int maxIndex = sums.indexOf(sums.stream().max(Float::compareTo).get());

Просто передайте первый список в очередь и .map его (картакак foreach, но возвращает результат для каждого элемента списка).

Что происходит на карте: для каждого элемента он находит самый высокий индекс для текущего значения f в списке 1. Это будет индекс текущего элемента в первомсписок.Затем он получает значение для этого индекса во втором списке.list2.get(list1.lastIndexOf(f)).Так что теперь вы добавляете текущее значение f к этому.Таким образом, для полной длины списка 1 вы выводите сумму двух значений, имеющих один и тот же индекс.

Тогда вам просто нужно .collect вернуть их обратно в список.

Наконец, чтобы найти максимальный индекс, я бы выбрал тот же подход, что и вы.

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