Хорошо ли использовать большой набор или эквивалентную карту с наборами в нем? - PullRequest
0 голосов
/ 04 января 2019

У меня есть несколько точек данных, собранных от разных компаний, идентифицированных companyId, и свойство имени каждой точки данных может дублироваться в одной компании или среди разных компаний. Проблема состоит в том, чтобы сгруппировать все точки данных по свойству имени, которое принадлежитдля разных компаний, что означает, что мы игнорируем точку данных, если ее компания уже существует в группе.

Например, точки данных:

название точки данных companyId
1--------------------- A
1 --------------------- A
1 --------------------- B
2 --------------------- A
3 --------------------- B

Результаты будут такими:

группа имен точек данных

A ================= (1, A) (2, A)
B ================= (1, B) (2, B)

Мы можем видеть, что вторая точка данных A от компании 1. была проигнорирована.

Насколько я знаю, есть два способадедупликация работы.
1.Строить Map<String(data point name), Set<Long(companyId)>>

Map<String, Set<Long>> dedup = new HashMap<>();
for(DataPoint dp : datapoints){
    String key = dp.getName();
    if(!dedup.contains(key)){
        dedup.put(key, new HashSet<Long>());
    }
    if(dedup.get(key).contains(dp.getCompanyId()){
        continue;
    }
    dedup.get(key).add(dp.getCompanyId());
}

2.Создать большой Set<String>

Set<String> dedup;
for(DataPoint dp : datapoints){
    String key = dp.getName() + dp.getCompanyId();
    if(dedup.contains(key)){
        continue;
    }
    dedup.add(key);
}

Итаккакой из них лучше или уместнее?

Ответы [ 2 ]

0 голосов
/ 04 января 2019

Самый простой способ сделать (1) будет:

Map<String, Set<Long>> dedup =
    datapoints.stream().collect(
        groupingBy(
            DataPoint::getName,
            mapping(DataPoint::getCompanyId, toSet()));

Самый простой способ сделать (2) будет:

Set<String> dedup =
    datapoints.stream()
        .map(d -> d.getName() + d.getCompanyId())
        .collect(toSet());

Выбор, который вы выберете, зависит от того, что вы пытаетесь сделать, поскольку они дают разные типы данных, а также потенциально разные результаты.

0 голосов
/ 04 января 2019

Метод (1) намного лучше, потому что метод 2 уничтожает информацию о типе.

Для таких случаев уже доступны готовые коллекции, если вы хотите хорошо протестированную надежную реализацию со многими дополнительными функциями.

Гуава: https://google.github.io/guava/releases/21.0/api/docs/com/google/common/collect/HashMultimap.html

Коллекции Eclipse: https://www.eclipse.org/collections/

Если вы просто хотите простую реализацию, вы можете следовать своему методу (1) и сделать это самостоятельно.

Результат будет примерно таким:

{
   "A": [1, 2],
   "B": [1, 2]
}

Несколько причин, почему я не предпочитаю метод 2:

  1. Метод не надежен. Если название компании заканчивается цифрой, возможно, у вас ложная дедупликация. Поэтому вам может потребоваться добавить специальный символ, например, такой: <id>~<name>
  2. Если позже вам понадобится рассмотреть еще один параметр, он станет более грязным. Возможно, вам придется сделать <id>~<name>~<pincode> и т. Д.,
  3. В методе 1 у вас есть дополнительное удобство, заключающееся в том, что вы можете поместить компонент компании напрямую, если вы реализуете хэш-код и равно, которые основаны только на поле companyId
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...