Fill Map without duplicating records

Asked

Viewed 254 times

1

I own a List of an object A. In this object, I have 2 attributes: Long and a BigDecimal.

How can I create a Map where the key will be Long and value will be the BigDecimal, using a lambda?

The problem is that the Long cannot repeat.

  • The name has now escaped me, but if I am not mistaken, there is a Colection that does not allow repetition within it. On this link is someone who has achieved something similar to what you want (in English) https://stackoverflow.com/questions/14476548/which-data-structure-to-use-for-keeping-a-list-unique-with-insertion-order-intac

  • as you have 2 different types within the same list?

  • Does this list have exactly two items? Or does it have Longs and BigDecimals alternating?

  • Guys, I’m sorry to ask...actually the list is for an object and this one has 2 attributes: Long and Bigdecimal.

2 answers

3


Let’s assume your class A have a method getX() that gives the value Long and a method getY() that gives the BigDecimal. With this, you can use the method Collectors.toMap:

List<A> suaLista = ...;
Map<Long, BigDecimal> map = suaLista.stream().collect(Collectors.toMap(A::getX, A::getY);

It is worth mentioning this detail of the method documentation:

If the Mapped Keys contain Uplicates (According to Object.equals(Object)), an IllegalStateException is thrown when the Collection Operation is performed.

Translating:

If the mapped keys contain duplicates (according to the Object.equals(Object)), one IllegalStateException is launched when the collection operation is performed.

Which means this exception will be thrown if your list has at least two objects with the same Longs.

If you want to accept duplicates, and take only one of them, that same documentation says the following:

If the Mapped Keys Might have Uplicates, use toMap(Function, Function, BinaryOperator) Instead.

Translating:

If mapped keys can have duplicates, use toMap(Function, Function, BinaryOperator) instead.

And to keep only the first key, then that would be:

List<A> suaLista = ...;
Map<Long, BigDecimal> map = suaLista.stream()
        .collect(Collectors.toMap(A::getX, A::getY, (p, q) -> p);

That one (p, q) -> p is the BinaryOperator that takes two values and returns the first.

  • @Douglas Are there duplicate keys in the past list? If so, how would you like them to be solved?

  • I’d take the first call and jump to the next.

  • @Douglas Reply edited.

3

You can use the library Collectors, the method toMap().

In this example, I have an object with two fields, chave and valor, which will be the respective key / value of the map.

It is also possible to handle duplicate keys using a função de merge, which is the third parameter of toMap()

In this scenario, he will prefer to keep the old value.

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;

public class Q319074 {

public static void main(String[] args) {

        Numero n1 = new Numero(Long.valueOf(1), new BigDecimal(10));
        Numero n2 = new Numero(Long.valueOf(1), new BigDecimal(20));
        Numero n3 = new Numero(Long.valueOf(3), new BigDecimal(30));

        Map<Long, BigDecimal> valores = Arrays.asList(n1, n2, n3)
                                        .stream()                                        
                                        .collect(Collectors.toMap(Numero::getChave,
                                                              Numero::getValor,
                                                              (valorAntigo, valorNovo) -> valorAntigo));

       System.out.println(valores);
   }
}

class Numero {

    private Long chave;
    private BigDecimal valor;

    Numero(Long chave, BigDecimal valor) {
        this.chave = chave;
        this.valor = valor;
    }

    public Long getChave() {
        return chave;
    }

    public BigDecimal getValor() {
        return valor;
    }
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.