Como encontrar a data mais recente do valor do mapa fornecido em java


10

Estou tendo um mapa de hash com valores abaixo, em valores que eu tenho como tipo de dados string. Gostaria de comparar todas as datas disponíveis no mapa e extrair apenas um valor-chave com uma data muito recente.

Eu gostaria de comparar com valores e não chaves.

Eu incluí o código abaixo

import java.util.HashMap;
import java.util.Map;

public class Test {

  public static void main(String[] args) {

      Map<String, String> map = new HashMap<>();
      map.put("1", "1999-01-01");
      map.put("2", "2013-10-11");
      map.put("3", "2011-02-20");
      map.put("4", "2014-09-09");

      map.forEach((k, v) -> System.out.println("Key : " + k + " Value : " + v));
    }

}

A saída esperada para este é:

Valor-chave 4 09-09-2014


ele precisa do maior valor, não key
Mangusta


Erro de design. Não coloque suas datas em seu mapa como strings. Coloque LocalDateobjetos. O restante do código provavelmente será o mesmo, salve a declaração do tipo do mapa.
Ole VV

Relacionado: Localizando as chaves do mapa com os valores mais altos (pode ocorrer igualdade) (na Revisão do Código de Troca de Pilha).
Ole VV

Respostas:


1

Isso deve fornecer a data mais recente (também conhecida como maior) em comparação com as outras.

      String max = map.values().stream().reduce("0000-00-00",
            (a, b) -> b.compareTo(a) >= 0 ? b
                  : a);

Se você também deseja a chave, faça isso e retorne um Map.Entry. Requer Java 9+

         Entry<String, String> ent =
            map.entrySet().stream().reduce(Map.entry("0", "0000-00-00"),
                  (a, b) -> b.getValue().compareTo(a.getValue()) >= 0 ? b
                        : a);

         System.out.println(ent.getKey() + " -> " ent.getValue());

Isso pressupõe que seu mapa não esteja vazio. se estiver vazio, ele retornará um nulo. Funciona com Java 8 ou superior

        Entry<String, String> ent = map.entrySet().stream().reduce(
            (a, b) -> b.getValue().compareTo(a.getValue()) >= 0 ? b
                  : a).orElseGet(() -> null);

Como obter a chave como resultado?
aprenda groovy

Veja minha adição. Pensei que você só queria o valor. Mea Culpa.
WJS

Estou recebendo um erro com seu novo código - Map.entry ("0", "0000-00-00") - diz que Method map.entry é indefinido para o tipo Map ..
learn groovy

Você deve estar executando algo mais antigo que o Java 9 (que foi quando isso foi adicionado). Vou oferecer uma alternativa e explicá-la.
WJS

Sim, eu estou usando Java 8
aprender Groovy

6

Use Collections.max com entrySet

Entry<String, String> max = Collections.max(map.entrySet(), Map.Entry.comparingByValue());

ou

Entry<String, String> max = Collections.max(map.entrySet(),
    new Comparator<Entry<String, String>>() {
        @Override
        public int compare(Entry<String, String> e1, Entry<String, String> e2) {
            return LocalDate.parse(e1.getValue()).compareTo(LocalDate.parse(e2.getValue()));
        }
});

O Map.Entry.comparingByValue()é bacana (desde o Java 8).
Ole VV

4

À primeira vista, o uso de literais String para representar Data não é uma boa abordagem e a torna mais frágil e propensa a erros. Você prefere usar LocalDateem primeiro lugar. No entanto, com a suposição de que você não tem controle sobre esse formato de dados (por exemplo, é proveniente de outro sistema de terceiros), ainda podemos conceber uma abordagem que resolva o problema em questão. Aqui está como fica.

Entry<String, String> maxEntry = map.entrySet().stream()
    .max(Comparator.comparing(e -> LocalDate.parse(e.getValue())))
    .orElseThrow(IllegalArgumentException::new);

O LocalDate.parseé usado para converter a representação em cadeia da data em uma LocalDateque é comparável. Isso Comparableé passado como uma chave para o Comparatormétodo de construção. E aqui está o par de valores-chave de saída após a execução bem-sucedida:

4=2014-09-09

Se você pode simplesmente dispensar a representação String da data, conforme sugerido acima, poderá tornar a solução acima muito mais simples e sucinta.

Entry<String, LocalDate> maxEntry = map.entrySet().stream()
    .max(Map.Entry.comparingByValue())
    .orElseThrow(IllegalArgumentException::new);

3

Isso deve funcionar

    Optional<Map.Entry<String, String>> result = map.entrySet().stream().max(Comparator.comparing(Map.Entry::getValue));
    System.out.println(result);

saída é Optional[4=2014-09-09]


Obrigado, querida .. mas eu estou procurando a chave no resultado
aprender Groovy

1

Você pode analisar a sequência LocalDatee ordená-la na ordem inversa

 Entry<String, String> res = map.entrySet()
                                .stream()
                                .sorted(Comparator.comparing((Entry<String, String> entry)->LocalDate.parse(entry.getValue())).reversed())
                                .findFirst()
                                .orElse(null);  // if not present return null or empty Entry

1

Você pode:

import java.util.Map.Entry;

Entry<String, String> maxEntry = map.entrySet()
                                    .stream()
                                    .max(Entry.comparingByValue());
                                    .orElseThrow(NoSuchElementException::new);   

ou:

Entry<String, String> max = Collections.max(map.entrySet(), Entry.comparingByValue());

Ambos produzirão o mesmo resultado.


O Map.Entry.comparingByValue()é bacana (desde o Java 8).
Ole VV
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.