Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a Map with immutable keys and no duplicates using Google Guava?

Tags:

java

guava

I'd like to create a key/value map structure using Google Guava where the keys cannot be modified but the values can. I also want the ability to use a predicate (or something similar) to iterate the Map and only retrieve those entries that have values.

For example, conceptually:

// start
Map data =
{Constants.KEY_NAME_1, Optional.absent()},
{Constants.KEY_NAME_2, Optional.absent()};

// succeeds
data.put(Constants.KEY_NAME_2, Optional.of("new_data"));

// finish
Map data =
{Constants.KEY_NAME_1, Optional.absent()},
{Constants.KEY_NAME_2, Optional("new_data")};

// fails
data.put(Constants.KEY_NAME_3, Optional.of("more_new_data"));

Any idea how to accomplish this?

-------- Solution --------

As per the comments below, I went with the ForwardingMap. The Implementation is straightforward

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ForwardingMap;
import com.google.common.collect.ImmutableList;
import java.util.Map;

Map<String, String> labelMap = ImmutableMap.<String, String> builder()
    .put("KEY_1", "data1")
    .put("KEY_2", "data2")
    .build();

MyCustomMap<String> map = new MyCustomMap(labelMap);

public class MyCustomMap<String> extends ForwardingMap<String, String> {

    private final Map<String, String> delegate;
    private final ImmutableMap<String, String> immutableMap;

    public MyCustomMap(Map<String, String> labelMap) {

        /*
            Check for duplicate values in the map here.  The construction of 
            the ImmutableMap above ensures that there are no duplicate
            keys.  Otherwise it will throw
            "IllegalArgumentException: Multiple entries with same key".
        */

        delegate = labelMap;
        immutableMap = ImmutableMap.<String, String>builder().putAll(delegate).build();
    }

    @Override
    protected Map<String, String> delegate() {
        return immutableMap;
    }
}
like image 679
TERACytE Avatar asked Nov 21 '25 02:11

TERACytE


1 Answers

Guava cannot do anything for you if your keys are not immutable; this is something you have to ensure yourself (by making sure that the class of all keys is an immutable class).

Even an ImmutableMap is not immune to this kind of mishap:

// Modify the key
victim.keySet().iterator().next().alterMe();

If what you wish to do is customize the behavior upon insertion/retrieval then you can use a ForwardingMap to wrap another Map instance.

Beware however that this class leaves you a lot of freedom, including that of breaking the Map contract, which you should obviously refrain from!

like image 118
fge Avatar answered Nov 23 '25 15:11

fge



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!