Mapa <K, V> Voltar ao mapa <V, Map <K, V >> após valor groupingBy, em vez de Map <Obj, List <Entry <K, V >>>

Greco:

Eu estou lutando com a manutenção das estruturas de dados que eu quero todas as operações em Java de streaming, provavelmente devido à falta de compreensão e prática adequada.

public class Main {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 1, 1, 2, 3, 3, 3, 3);

            //Group by
            Map <Integer, Long> countGrouped = list.stream().collect(
                    Collectors.groupingBy(
                            x -> x, Collectors.counting()));
            System.out.println("group by value, count " + countGrouped);

            //Sort desc
            Map <Integer, Long> descendingSorted = new LinkedHashMap<>();
            countGrouped.entrySet().stream()
                .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
                .forEachOrdered(x -> descendingSorted.put(x.getKey(), x.getValue()));
            System.out.println("sorted " + descendingSorted);

            //filter
            Map <Integer, Long> filtered = new LinkedHashMap<>();
            descendingSorted.entrySet().stream()
                .filter(x -> x.getValue() >= 2)
                .forEach(x -> filtered.put(x.getKey(), x.getValue()));;
            System.out.println("filtered " + filtered);

            //Split groups
            Map<Object, List<Entry<Integer, Long>>> groups = filtered.entrySet().stream()
                    .collect(Collectors.groupingBy(x -> x.getValue()));
            System.out.println("grouped " + groups);
    }
}

Resultando em

group by value, count {1=3, 2=1, 3=4}
sorted {3=4, 1=3, 2=1}
filtered {3=4, 1=3}
grouped {3=[1=3], 4=[3=4]}

o que é correto, mas eu estou recebendo em estruturas de dados cada vez mais abstrusas sem sentido particular, como você pode ver, terminando num (wtf?) Map<Object, List<Entry<Integer, Long>>>como você pode ver. Embora possa ser apenas um Map<Int, Map<Int, Int>>.

Portanto, a questão específica é, como faço para transformar e conter as saídas de estrutura de dados resultantes de operações de fluxo?

Eu vi os coletores fornecendo transformar as operações toMap (...), e acho que este é o caminho a percorrer, mas eu sou incapaz (devido à falta de conhecimento adequado, eu acho) para fazê-lo funcionar.

Neste caso, parece-me que será muito ajudado por uma explicação didática, link para recursos abrangentes para obter uma melhor compreensão de córregos e programação funcional, ou coisas como esta, mais do que a solução real para o caso particular (o que seria bom para um exercício, mas você começa a idéia)

Holger:

É um pouco surpreendente que você tem dificuldades aqui, como você já mostrado o conhecimento de todas as coisas necessárias. Você sabe que groupingBypode tomar outra Collector, você nomeou o caminho certo, toMapjá, e você já usou funções para extrair os Map.Entryvalores já.

Combinando essas coisas, dá-lhe

Map<Long, Map<Integer, Long>> groups = filtered.entrySet().stream()
    .collect(Collectors.groupingBy(x -> x.getValue(),
        Collectors.toMap(x -> x.getKey(), x -> x.getValue())));
System.out.println("grouped " + groups);

Para demonstrar melhor a operação, I mudou a entrada para

List<Integer> list = Arrays.asList(1, 1, 1, 2, 3, 3, 3, 3, 4, 4, 4);

o que resulta em

grouped {3=[1=3, 4=3], 4=[3=4]}

porém, não há nenhum ponto em repetir as contagens que são sempre o mesmo que o exterior mapeia chaves. Assim, uma alternativa seria

Map<Long, List<Integer>> groups = filtered.entrySet().stream()
    .collect(Collectors.groupingBy(Map.Entry::getValue,
        Collectors.mapping(Map.Entry::getKey, Collectors.toList())));
System.out.println("grouped " + groups);

o que leva a

grouped {3=[1, 4], 4=[3]}

Note que você não deve usar forEach/ forEachOrdereda putem um mapa. Seus passos intermediários deve, antes, ser

//Sort desc
Map<Integer, Long> descendingSorted = countGrouped.entrySet().stream()
    .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
        (a,b) -> { throw new AssertionError(); }, LinkedHashMap::new));
System.out.println("sorted " + descendingSorted);

//filter
Map<Integer, Long> filtered = descendingSorted.entrySet().stream()
    .filter(x -> x.getValue() >= 2)
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
        (a,b) -> { throw new AssertionError(); }, LinkedHashMap::new));
System.out.println("filtered " + filtered);

O toMapcoletor de aceitar um mapa de fábrica forças dos EUA para fornecer uma função direta, mas desde a nossa entrada já é um mapa que deve ter chaves distintas, forneci uma função sempre jogando aqui, como algo seria muito errado, se duplicatas aparecer.

Mas nota que forçar todas estas operações para recolher em novos mapas é desnecessariamente complicado e ineficiente. Também há nenhum ponto na classificação dos dados inteiros em primeiro lugar e reduzir a quantidade de dados por meio filterdepois. Filtrando primeira seria, potencialmente, reduzir o trabalho da etapa de classificação Considerando que o resultado da operação do filtro não deve depender do fim.

É muito melhor fazer toda a operação em um único gasoduto

List<Integer> list = Arrays.asList(1, 1, 1, 2, 3, 3, 3, 3, 4, 4, 4);

Map<Integer, Long> countGrouped = list.stream().collect(
    Collectors.groupingBy(x -> x, Collectors.counting()));
System.out.println("group by value, count " + countGrouped);

Map<Long, List<Integer>> groups = countGrouped.entrySet().stream()
    .filter(x -> x.getValue() >= 2)
    .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
    .collect(Collectors.groupingBy(Map.Entry::getValue, LinkedHashMap::new, 
        Collectors.mapping(Map.Entry::getKey, Collectors.toList())));

System.out.println("grouped " + groups);

Note-se que ao contrário do código anterior, agora a última operação de agrupamento irá também manter a ordem, o que resulta em

grouped {4=[3], 3=[1, 4]}

ou seja, os grupos são classificadas segundo descendente contagem.

Desde a contagem é a chave do mapa resultante, também podemos usar um mapa intrinsecamente ordenada como tipo e omitir a etapa de classificação:

Map<Long, List<Integer>> groups = countGrouped.entrySet().stream()
    .filter(x -> x.getValue() >= 2)
    .collect(Collectors.groupingBy(Map.Entry::getValue,
        () -> new TreeMap<>(Comparator.<Long>reverseOrder()),
        Collectors.mapping(Map.Entry::getKey, Collectors.toList())));

Os principais mentiras diferença no comportamento do mapa resultado após a operação de fluxo, por exemplo, se você inserir mais elementos a ele, como o TreeMapirá inserir novas chaves de acordo com a ordem descendente enquanto que LinkedHashMapirá acrescentar-los até o fim, mantendo a ordem de inserção.

Este artigo é coletado da Internet.

Se houver alguma infração, entre em [email protected] Delete.

editar em
0

deixe-me dizer algumas palavras

0comentários
loginDepois de participar da revisão

Artigos relacionados

TOP lista

  1. 1

    R Shiny: use HTML em funções (como textInput, checkboxGroupInput)

  2. 2

    O Chromium e o Firefox exibem as cores de maneira diferente e não sei qual deles está fazendo certo

  3. 3

    Como assinar digitalmente um documento PDF com assinatura e texto visíveis usando Java

  4. 4

    R Folheto. Dados de pontos de grupo em células para resumir muitos pontos de dados

  5. 5

    Gerenciar recurso shake de Windows Aero com barra de título personalizado

  6. 6

    Como obter dados API adequados para o aplicativo angular?

  7. 7

    UITextView não está exibindo texto longo

  8. 8

    Por que meus intervalos de confiança de 95% da minha regressão multivariada estão sendo plotados como uma linha de loess?

  9. 9

    Acessando relatório de campanhas na AdMob usando a API do Adsense

  10. 10

    Usando o plug-in Platform.js do Google

  11. 11

    Como posso modificar esse algoritmo de linha de visada para aceitar raios que passam pelos cantos?

  12. 12

    Dependência circular de diálogo personalizado

  13. 13

    Coloque uma caixa de texto HTML em uma imagem em uma posição fixa para site para desktop e celular

  14. 14

    iOS: como adicionar sombra projetada e sombra de traço no UIView?

  15. 15

    Como usar a caixa de diálogo de seleção de nomes com VBA para enviar e-mail para mais de um destinatário?

  16. 16

    Tabela CSS: barra de rolagem para a primeira coluna e largura automática para a coluna restante

  17. 17

    How to create dynamic navigation menu select from database using Codeigniter?

  18. 18

    Converter valores de linha SQL em colunas

  19. 19

    ChartJS, várias linhas no rótulo do gráfico de barras

  20. 20

    用@StyleableRes注释的getStyledAttributes。禁止警告

  21. 21

    não é possível adicionar dependência para com.google.android.gms.tasks.OnSuccessListener

quentelabel

Arquivo