Возвращение индекса списка при обновлении счетчика сравнительной функции Comparator - PullRequest
0 голосов
/ 05 февраля 2019

Я сортирую один список, используя другой список.Цель сортировки - перенести элементы, которые присутствуют в массиве B, в верхнюю часть массива A, если массив содержит эти элементы.

Например:

inputA = {"A", "B", "G"} inputB = {"G", "F"} output should be A = {"G", "A", "B"}

Myсортировка кода выглядит следующим образом:

Collections.sort( inputA, 
           Comparator.comparing( a -> inputB.indexOf( a ) > -1 ? -1 : a.getIndex()));

Мой настоящий код не такой, но идея та же.Реальный код содержит два общих списка со сложными объектами.

Мой код сортировки работает правильно.Что я хочу сделать, так это когда я возвращаю -1 или a.getIndex(), я хочу получить счетчик возвращенных значений no.of -1.

Как я могу сделать это внутри этого кода?Любые предложения?

ОБНОВЛЕНИЕ

inputA = {"A", "B", "C", "G"} inputB = {"G", "B"} output should be A = {"B", "G", "A", "C"}

Вывод, который я получаю output = {"B", "G", "C", "A"}

В оригинале inputA элемент «C» следует после элемента «A».Но в моем результате я получаю его в обратном порядке.

Как это исправить?

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

Ответы [ 4 ]

0 голосов
/ 12 февраля 2019

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

Так что если у вас есть

List<String> inputA = Arrays.asList("A", "B", "G");
List<String> inputB = Arrays.asList("G", "F");

и вы используете

inputA.sort(Comparator.comparing(inputB::contains).reversed());

вы получите заказ [G, A, B].

Аналогично,

List<String> inputA = Arrays.asList("A", "B", "C", "G");
List<String> inputB = Arrays.asList("G", "B");

inputA.sort(Comparator.comparing(inputB::contains).reversed());

приведет к [B, G, A, C].Поскольку единственным критерием для предоставленного компаратора является то, содержится ли элемент в другом списке, относительный порядок элементов в каждой из двух групп («содержится» и «не содержится») не изменится.

Примечаниечто если listB достаточно велико, повторный линейный поиск может вызвать проблемы с производительностью.Это можно решить с помощью временного хэша, установленного для быстрого поиска:

inputA.sort(Comparator.comparing(new HashSet<>(inputB)::contains).reversed());
0 голосов
/ 05 февраля 2019

Вы можете сохранить счетчик, который увеличивается каждый раз, когда возвращается -1.Вот ваш модифицированный код:

AtomicInteger count = new AtomicInteger(0);
Collections.sort(a, Comparator.comparing(s -> {
    if (b.indexOf(s) > -1) {
        count.incrementAndGet();
        return -1;
    }
    return a.indexOf(s);
}));
System.out.println(count.get());
0 голосов
/ 05 февраля 2019

Что-то вроде этого должно сделать:

Vector<String> inputA = new Vector();
Vector<String> inputB = new Vector();
// fill elements/ get userelements 
// ...

//push to front:
for(String element:inputB){
    if(inputA.remove(element)){
        inputA.add(0, element);
    }
}

Некоторый связанный список как контейнер должен быть более производительным.Массивы будут иметь много копий - не лучший выбор.Но выбор контейнера зависит от вас ...

0 голосов
/ 05 февраля 2019

Из того, что я вижу, число -1 s эквивалентно размеру пересечения inputA и inputB.Вы можете использовать следующий фрагмент, чтобы получить это значение:

var distinctB = Set.copyOf(inputB);
long commonSize = inputA.stream().filter(distinctB::contains).count();

Это предполагает, что inputA и inputB являются некоторыми Collection (вы указали универсальные списки ).

...