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

aprender groovy
fonte
ele precisa do maior valor, não key
Mangusta
11
OK, tente stackoverflow.com/questions/109383/…
Scary Wombat
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);
WJS
fonte
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()));
        }
});
bathudaide
fonte
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);
Ravindra Ranwala
fonte
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]

Rajkumar Natarajan
fonte
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
Piscina morta
fonte
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.

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