Java - как удалить дубликаты из коллекции временных меток? - PullRequest
0 голосов
/ 24 апреля 2019

У меня есть список временных меток в миллисекундах, и я хочу сравнить их и удалить дубликаты, не считая миллисекундную часть. И обрабатывать каждое уникальное значение.

Например, millis2 и millis3 - это разные значения при сравнении без усечения миллисекундной части (2:28:14.100 против 2:28:14.200). Но мне нужно не обращать внимания на миллис, и если эти два значения сравниваются усеченными до секунд, они будут считаться дубликатами.

Поэтому я решил создать список временных меток, отсортировать его в обратном порядке. Затем выполните итерацию по проверке коллекции, если усеченные значения не равны. И добавьте уникальные значения к List<Long> deduped.

    Long millis0 = 1554052261000L; // Sunday, March 31, 2019 5:11:01 PM
    Long millis1 = 1557023292000L; // Sunday, May 5, 2019 2:28:12 AM
    Long millis2 = 1557023294100L; // Sunday, May 5, 2019 2:28:14.100 AM
    Long millis3 = 1557023294200L; // Sunday, May 5, 2019 2:28:14.200 AM

    List<Long> initialTimestamps = Arrays.asList(millis2, millis3, millis0, millis1);

    Comparator<Long> comparator = Collections.reverseOrder();
    Collections.sort(initialTimestamps, comparator);

    Long prevTs = null;
    List<Long> deduped = new ArrayList<>();

    for (Long ts: initialTimestamps) {
        if (prevTs != null && !millisToSeconds(prevTs).equals(millisToSeconds(ts))) {
        deduped.add(prevTs);
        process(prevTs)
    }
    prevTs = ts;
    deduped.add(prevTs);
    process(prevTs)
}

Однако при распечатке содержимого deduped имеются дубликаты:

Deduped timestamps ->
1557023294200
1557023294100
1557023294100
1557023292000
1557023292000
1554052261000

Но я ожидаю, что после дедупликации останутся только 1557023294, 1557023292 и 1554052261. Что мне здесь не хватает?

1 Ответ

4 голосов
/ 24 апреля 2019

Если вы можете использовать Java 8, то вы можете использовать stream().distinct():

public static void main(String[] args) throws Exception {
    Long millis0 = 1554052261000L; // Sunday, March 31, 2019 5:11:01 PM
    Long millis1 = 1557023292000L; // Sunday, May 5, 2019 2:28:12 AM
    Long millis2 = 1557023294100L; // Sunday, May 5, 2019 2:28:14.100 AM
    Long millis3 = 1557023294200L; // Sunday, May 5, 2019 2:28:14.200 AM

    List<Long> initialTimestamps = Arrays.asList(millis2, millis3, millis0, millis1);
    List<Long> unique = initialTimestamps.stream().distinct().collect(Collectors.toList());

    System.out.println(unique);
}

Для Java <8, вы можете поместить их в <code>Set:

public static void main(String[] args) throws Exception {
    Long millis0 = 100L; // Sunday, March 31, 2019 5:11:01 PM
    Long millis1 = 100L; // Sunday, May 5, 2019 2:28:12 AM
    Long millis2 = 200L; // Sunday, May 5, 2019 2:28:14.100 AM
    Long millis3 = 200L; // Sunday, May 5, 2019 2:28:14.200 AM

    List<Long> initialTimestamps = Arrays.asList(millis2, millis3, millis0, millis1);
    Set<Long> unique = new HashSet<Long>(initialTimestamps);

    System.out.println(unique);
}

Обновление

В соответствии с вашим требованием игнорировать миллисекунды, вы можете использовать Map (если вы хотите сохранить миллисекунды) или использовать один из подходов, описанных выше, если вам не нужны миллисекунды. В этом случае просто разделите значения на 1_000

public static void main(String[] args) throws Exception {
    Long millis0 = 1554052261000L; // Sunday, March 31, 2019 5:11:01 PM
    Long millis1 = 1557023292000L; // Sunday, May 5, 2019 2:28:12 AM
    Long millis2 = 1557023294100L; // Sunday, May 5, 2019 2:28:14.100 AM
    Long millis3 = 1557023294200L; // Sunday, May 5, 2019 2:28:14.200 AM

    List<Long> initialTimestamps = Arrays.asList(millis2, millis3, millis0, millis1);
    Map<Long, Long> unique = new HashMap<>();

    for (Long timestamp : initialTimestamps) {
        unique.put(timestamp / 1000, timestamp);
    }

    System.out.println(unique.values());
}

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

if (!unique.containsKey(timestamp / 1000)) {
    unique.put(timestamp / 1000, timestamp);
}

вместо просто put(). Если вы хотите сохранить первоначальный порядок всех временных меток, вам следует использовать LinkedHashMap вместо HashMap

...