Is it possible to have a method requiring a HashMap and be able to provide any HashMap with Strings as keys? Some kind of generic data Type to put instead of 'Value'?
public void example(HashMap<String, Value> hashMap) {
//Stuff
}
example(new HashMap<String, Integer>);
HashMap<String, String> exampleMap = new HashMap<>();
example(exampleMap);
Alternatively, is it possible to check the key/value type of the map, other than looping through all the keys/value and check instanceof (without stopping it with return)?
public Boolean example(HashMap<String, Value> hashMap) {
for (Value value : hashMap.values())) {
if (value instanceof String) {
return true; //<- Unwanted
}
}
}
EDIT:
Let me explain my problem a bit further. I have a method:
public static Object getEIC(HashMap<String, Object> map, String key) {
for (String keys : map.keySet()) {
if (keys.equalsIgnoreCase(key)) {
return map.get(keys);
}
}
return null;
}
EIC stands for equalsIgnoreCase. So I need some generic return Type as well. Thanks for the answers so far, and thanks on forehand for the answers on this!
You could do:
HashMap<String, Object>
But that's terrible though because then you end up doing instanceof all the time. What you really need to do is understand what the key problem is and then think of inheritance. Can you define an interface that all your value objects would implement? For instance GeometricShape which could be implemented by Rectangle and Circle.
Also, you can define a HashMap as follows:
HashMap<String, ? extends SomeClass>
And as others pointed out, it's best to use the interface Map rather than a specific implementation e.g. HashMap.
Lastly, as I pointed out in a comment, it seems you are just trying to implement a Map<key, value> where you want to have case-insensitive keys. If so have a look at www.stackoverflow.com/questions/8236945/
The answer is to use a CaseInsensitiveMap. Thanks, everyone, for helping me and especially David Brossard for suggesting this.
You can implement the static method you are looking for using generics:
public static <V> V getEIC(Map<String, V> map, String key) {
for (String k : map.keySet()) {
if (k.equalsIgnoreCase(key)) {
return map.get(key);
}
}
return null;
}
however, you may wish to consider an enhanced Map Is there a good way to have a Map<String, ?> get and put ignoring case?
Note, however, that there is a subtle difference between this solution and using case-less equals - an ordinary Map<String,V> could hold a value for "Key" and "key" while a case-less Map would not. This method would arbitrarily choose one of them while a case-less Map would choose the most recent addition.
Yes, but requiring Map<String, Value> is better. If you don't care what value is ask for Map<String, ?>. If you do but don't yet know what it will be, use Map<String, ? extends T>
Requiring HashMap is programing to an implementation rather than an interface. There is rarely a good reason to do that.
And no. If you don't trust whoever built the map and want to be sure the map contains only the types it's supposed to contain you have to loop and check each one. However, you can abstract that away in a method that will check for you so you don't have to look at it.
public class CheckedCast
{
public static <K,V> Map<K,V> mapOf(Class<? extends K> classK,
Class<? extends V> classV,
Map<?,?> m)
{
for (Map.Entry<?, ?> e: m.entrySet())
{
classK.cast( e.getKey() );
classV.cast( e.getValue() );
}
#SuppressWarnings("unchecked")
Map<K,V> result = (Map<K,V>) m;
return result;
}
}
Related
I want your help for creating a data structure/ Collection which supports read and insert functionality and prevents deletion/removal of records.
One way i could think of is , to create a customized collection ( like myHashMap ) and override all the delete/remove methods and thus prevent removal/deletion of records? But this approach will not work if the Object is having removal method as Final.
Please suggest any better way ..!!!!
You can create your own arraylist by overriding the methods like remove() with unsupported operation exception. If you want you can also declare arraylist like this.
ArrayList<String> myList = new ArrayList<String>() {
#Override
public boolean remove(String str) {
//If you want, you can throw Unsupported operation exception also.
return false;
}
};
There may be some other good approaches, you can check answers from others also.
You can create your Map wrapper and provide only the methods you want to :
class MyHashMap<K, V> {
Map<K, V> map;
public MyHashMap(Map<K, V> map) {
this.map = map;
}
public V put(K key, V value) {
return map.put(key, value);
}
public V get(K key) {
return map.get(key);
}
// other methods you want
}
example:
MyHashMap<String, String> myMap = new MyHashMap<>(new HashMap<>());
I have a class which is basically wrapper around a Map (that also holds some business logic obviously).
What I would like to be able to do is this:
for(Object o: instanceOfMyClass) { ... }
So I want to loop over the values of the Map inside my class. Which interfaces do I need to implement in my class (Iterator, Iterable, ...)?
I guess in the interface to implement I somehow need to return an Interator; how can I "reuse" the iterator for the Map (through Map.entrySet()) keeping in mind that I only want to have the values exposed in the iterator of my class?
Thanks a lot!
It's as simple as implementing Iterable. In your case, you want to implement Iterable<SomeType>:
public class Main implements Iterable<String>
{
private final Map<String, String> myMap = new HashMap<>();
{
myMap.put("hello", "world");
myMap.put("aaa", "bbb");
}
#Override
public Iterator<String> iterator()
{
return Collections.unmodifiableMap(myMap).values().iterator();
}
}
Here's a test method, with the output below:
public static void main(String... args)
{
for (String entry : new Main())
{
System.out.println("Value: " + entry);
}
}
Value: bbb Value: world
Implementing Iterable is what allows you to use the for(Foo f : foo) syntax, but if you're wrapping a Map you might want to implement the Map.forEach() method instead. It's a little bit nicer when you can directly address the key and value separately (although the question is now about accessing values only).
// Mostly copied from Map.forEach()
// Adjust generic parameters if necessary
public void forEach(BiConsumer<? super K, ? super V> action) {
Objects.requireNonNull(action);
for (Map.Entry<K, V> entry : internalMap.entrySet()) {
K k;
V v;
try {
k = entry.getKey();
v = entry.getValue();
} catch(IllegalStateException ise) {
// this usually means the entry is no longer in the map.
throw new ConcurrentModificationException(ise);
}
action.accept(k, v);
}
}
If the default implementation is enough, you can of course just delegate to internalMap.forEach(action);.
I have a hashmap<String, String> which contains around one thousand entries.
Now I have to expose it in such way that it cannot be modified outside class. So I wrote like
public static Map<String, String> getResponseCodeSource()
{
return Collections.unmodifiableMap(codeMsgMap);
}
This method is called very frequently. My questions are 1. Will this cause performance issue? 2.Is method (unmodifiableMap) iterating over Map or this will perform its activity in O(constant) complexity ?
It's a very thin implementation:
public static <K,V> Map<K,V> unmodifiableMap(Map<? extends K, ? extends V> m) {
return new UnmodifiableMap<>(m);
}
and constructor code:
UnmodifiableMap(Map<? extends K, ? extends V> m) {
if (m==null)
throw new NullPointerException();
this.m = m;
}
So as you see complexity is O(1).
The Map returned from Collections.unmodifiableMap(Map) will be a thin proxy to the real underlying map with some methods disabled (put etc.). There is no reason to expect it to take a copy of the underlying map.
Returns: an unmodifiable view of the specified map.
Remember however that the unmodifiable map is only a view of the underlying map so changes in the underlying map will be reflected in the unmodifiable one. It would therefore be safe to do:
static final Map<String,String> codeMsgMap = new HashMap<>();
// Changes in the above map will be reflected here.
static final Map<String,String> unmodifiableCodeMsgMap = Collections.unmodifiableMap(codeMsgMap);
public static Map<String, String> getResponseCodeSource() {
return unmodifiableCodeMsgMap;
}
On the complexity question Sergey Pauk covers that nicely.
This question already has answers here:
How to convert List to Map?
(20 answers)
Closed 7 years ago.
I would like to find a way to take the object specific routine below and abstract it into a method that you can pass a class, list, and fieldname to get back a Map.
If I could get a general pointer on the pattern used or , etc that could get me started in the right direction.
Map<String,Role> mapped_roles = new HashMap<String,Role>();
List<Role> p_roles = (List<Role>) c.list();
for (Role el : p_roles) {
mapped_roles.put(el.getName(), el);
}
to this? (Pseudo code)
Map<String,?> MapMe(Class clz, Collection list, String methodName)
Map<String,?> map = new HashMap<String,?>();
for (clz el : list) {
map.put(el.methodName(), el);
}
is it possible?
Using Guava (formerly Google Collections):
Map<String,Role> mappedRoles = Maps.uniqueIndex(yourList, Functions.toStringFunction());
Or, if you want to supply your own method that makes a String out of the object:
Map<String,Role> mappedRoles = Maps.uniqueIndex(yourList, new Function<Role,String>() {
public String apply(Role from) {
return from.getName(); // or something else
}});
Here's what I would do. I am not entirely sure if I am handling generics right, but oh well:
public <T> Map<String, T> mapMe(Collection<T> list) {
Map<String, T> map = new HashMap<String, T>();
for (T el : list) {
map.put(el.toString(), el);
}
return map;
}
Just pass a Collection to it, and have your classes implement toString() to return the name. Polymorphism will take care of it.
Java 8 streams and method references make this so easy you don't need a helper method for it.
Map<String, Foo> map = listOfFoos.stream()
.collect(Collectors.toMap(Foo::getName, Function.identity()));
If there may be duplicate keys, you can aggregate the values with the toMap overload that takes a value merge function, or you can use groupingBy to collect into a list:
//taken right from the Collectors javadoc
Map<Department, List<Employee>> byDept = employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment));
As shown above, none of this is specific to String -- you can create an index on any type.
If you have a lot of objects to process and/or your indexing function is expensive, you can go parallel by using Collection.parallelStream() or stream().parallel() (they do the same thing). In that case you might use toConcurrentMap or groupingByConcurrent, as they allow the stream implementation to just blast elements into a ConcurrentMap instead of making separate maps for each thread and then merging them.
If you don't want to commit to Foo::getName (or any specific method) at the call site, you can use a Function passed in by a caller, stored in a field, etc.. Whoever actually creates the Function can still take advantage of method reference or lambda syntax.
Avoid reflection like the plague.
Unfortunately, Java's syntax for this is verbose. (A recent JDK7 proposal would make it much more consise.)
interface ToString<T> {
String toString(T obj);
}
public static <T> Map<String,T> stringIndexOf(
Iterable<T> things,
ToString<T> toString
) {
Map<String,T> map = new HashMap<String,T>();
for (T thing : things) {
map.put(toString.toString(thing), thing);
}
return map;
}
Currently call as:
Map<String,Thing> map = stringIndexOf(
things,
new ToString<Thing>() { public String toString(Thing thing) {
return thing.getSomething();
}
);
In JDK7, it may be something like:
Map<String,Thing> map = stringIndexOf(
things,
{ thing -> thing.getSomething(); }
);
(Might need a yield in there.)
Using reflection and generics:
public static <T> Map<String, T> MapMe(Class<T> clz, Collection<T> list, String methodName)
throws Exception{
Map<String, T> map = new HashMap<String, T>();
Method method = clz.getMethod(methodName);
for (T el : list){
map.put((String)method.invoke(el), el);
}
return map;
}
In your documentation, make sure you mention that the return type of the method must be a String. Otherwise, it will throw a ClassCastException when it tries to cast the return value.
If you're sure that each object in the List will have a unique index, use Guava with Jorn's suggestion of Maps.uniqueIndex.
If, on the other hand, more than one object may have the same value for the index field (which, while not true for your specific example perhaps, is true in many use cases for this sort of thing), the more general way do this indexing is to use Multimaps.index(Iterable<V> values, Function<? super V,K> keyFunction) to create an ImmutableListMultimap<K,V> that maps each key to one or more matching values.
Here's an example that uses a custom Function that creates an index on a specific property of an object:
List<Foo> foos = ...
ImmutableListMultimap<String, Foo> index = Multimaps.index(foos,
new Function<Foo, String>() {
public String apply(Foo input) {
return input.getBar();
}
});
// iterate over all Foos that have "baz" as their Bar property
for (Foo foo : index.get("baz")) { ... }
I need to create an empty map.
if (fileParameters == null)
fileParameters = (HashMap<String, String>) Collections.EMPTY_MAP;
The problem is that the above code produces this warning:
Type safety: Unchecked cast from Map to HashMap
What is the best way to create this empty map?
1) If the Map can be immutable:
Collections.emptyMap()
// or, in some cases:
Collections.<String, String>emptyMap()
You'll have to use the latter sometimes when the compiler cannot automatically figure out what kind of Map is needed (this is called type inference). For example, consider a method declared like this:
public void foobar(Map<String, String> map){ ... }
When passing the empty Map directly to it, you have to be explicit about the type:
foobar(Collections.emptyMap()); // doesn't compile
foobar(Collections.<String, String>emptyMap()); // works fine
2) If you need to be able to modify the Map, then for example:
new HashMap<String, String>()
(as tehblanx pointed out)
Addendum: If your project uses Guava, you have the following alternatives:
1) Immutable map:
ImmutableMap.of()
// or:
ImmutableMap.<String, String>of()
Granted, no big benefits here compared to Collections.emptyMap(). From the Javadoc:
This map behaves and performs comparably to Collections.emptyMap(),
and is preferable mainly for consistency and maintainability of your
code.
2) Map that you can modify:
Maps.newHashMap()
// or:
Maps.<String, String>newHashMap()
Maps contains similar factory methods for instantiating other types of maps as well, such as TreeMap or LinkedHashMap.
Update (2018): On Java 9 or newer, the shortest code for creating an immutable empty map is:
Map.of()
...using the new convenience factory methods from JEP 269. 😎
Collections.emptyMap()
The emptyMap method of the Collections class.
If you need an instance of HashMap, the best way is:
fileParameters = new HashMap<String,String>();
Since Map is an interface, you need to pick some class that instantiates it if you want to create an empty instance. HashMap seems as good as any other - so just use that.
Either Collections.emptyMap(), or if type inference doesn't work in your case,
Collections.<String, String>emptyMap()
Since in many cases an empty map is used for null-safe design, you can utilize the nullToEmpty utility method:
class MapUtils {
static <K,V> Map<K,V> nullToEmpty(Map<K,V> map) {
if (map != null) {
return map;
} else {
return Collections.<K,V>emptyMap(); // or guava ImmutableMap.of()
}
}
}
Similarly for sets:
class SetUtils {
static <T> Set<T> nullToEmpty(Set<T> set) {
if (set != null) {
return set;
} else {
return Collections.<T>emptySet();
}
}
}
and lists:
class ListUtils {
static <T> List<T> nullToEmpty(List<T> list) {
if (list != null) {
return list;
} else {
return Collections.<T>emptyList();
}
}
}
What about :
Map<String, String> s = Collections.emptyMap();
You can use:
Collections<String, String>.emptyMap();