There is an useful class in android (at least for me). The Bundle class which allows you to put a kind of pair Key Value. But the value can be a different established classes of objects.
For example:
Bundle mBundle = new Bundle();
mBundle.putInt("Number One", 1);
mBundle.putBoolean("True", true);
There is a similar class in java?
Not that I know of, but it's fairly easy to reproduce with a HashMap:
public class Bundle extends HashMap<String,Object>{
public void putString(String key, String str){
put(key, str);
}
public String getString(String key){
Object o = get(key);
if(o!=null && o instanceof String)
return (String) o;
return null;
}
public void putInteger(String key, int anInt){
put(key, new Integer(anInt));
}
public Integer getInteger(String key){
Object o = get(key);
if(o!=null && o instanceof Integer)
return (Integer) o;
return null;
}
...
}
I don't think Java contains this kind of Object by default but you can create one:
public class Bundle extends HashMap<String, Object> {
public void putInt(String key, int value) {
put(key, value);
}
public void putString(String key, String value) {
put(key, value);
}
public Integer getInt(String key) {
if (containsKey(key) && get(key) instanceof Integer) {
return (Integer) get(key);
} else {
return null;
}
}
public String getString(String key) {
if (containsKey(key) && get(key) instanceof String) {
return (String) get(key);
} else {
return null;
}
}
}
Related
I have a class MapEntry to implement Hashmap. I need to implement a method where I can get key from value and method delete. I know that HashMap does not implement such method as getValue but my prof asked to do this. I'm new to programming how it's a little bit hard for me right now. I'll appreciate any help.
public class MapEntry<K,V> {
MapEntry<K,V> next;
K key;
V value;
public MapEntry(K key, V value) {
this.setKey(key);
this.setValue(value);
}
public void setKey( K key){
this.key=key;
}
public void setValue(V value){
this.value=value;
}
public K getKey(){
return key;
}
public V getValue(){
return value;
}
public void setNext(MapEntry<K,V> next) {
this.next = next;
}
public MapEntry<K, V> getNext() {
return next;
}
}
public class HashMap{
private int DEFAULT_CAPACITY = 10;
private MapEntry<String,Double>[] Hash;
private int size;
public HashMap() {
Hash = new MapEntry[DEFAULT_CAPACITY];
}
public boolean isEmpty(){
if(size!= 0){
return false;
}
else{
return true;
}
}
public int getHashCode(String key){
int bucketIndex = key.hashCode()%Hash.length;
return bucketIndex;
}
public Double get(String key){
if(key == null){
try {
throw new IllegalAccessException("Null key");
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
MapEntry<String,Double> entry = Hash[getHashCode(key)];
while (entry != null && !key.equals(entry.getKey()))
entry = entry.getNext();
if(entry != null)
return entry.getValue();
else
return null;
}
}
public void put(String key, double value){
int keyBucket =hash(key);
MapEntry<String,Double> temp = Hash[keyBucket];
while (temp !=null){
if((temp.key == null && key == null)
|| (temp.key != null && temp.key.equals(key))){
temp.value = value;
return;
}
temp = temp.next;
}
Hash[keyBucket] = new MapEntry<String, Double>(key,value);
size++;
}
public void delete (String key) throws IllegalAccessException {
if(key == null){
throw new IllegalAccessException("Null key");
}
}
private int hash(String key){
if(key == null){
return 0;
}else {
return Math.abs(key.hashCode()% this.Hash.length);
}
}
public static void main(String[] args) {
HashMap hashMap = new HashMap();
hashMap.put("value", 2.2);
hashMap.put("bob", 2.3);
System.out.println(hashMap.get("value"));
System.out.println(hashMap.get("bob"));
System.out.println(hashMap.size);
System.out.println(hashMap.getHashCode("value"));
System.out.println(hashMap.getHashCode("bob"));
System.out.println(hashMap.isEmpty());
}
}
I think the basic algo will be :
Iterate through all the values one by one
If your value matches the desired result, retrieve the key from that entry.
To delete that entry, simply remove that entry
Note : Doesn't work properly if you have multiple entries of same value.
I have this problem by this moment, I got a class with two methods with the same erasure:
public class VO implements Map<String,String> , Serializable{
public synchronized String put (Object key, Object value){
if (key == null)
return null;
if (value == null)
return remove(key);
String stringKey = key.toString();
String stringValue = value.toString();
if (value instanceof Boolean)
stringValue = ((Boolean)value) ? "Y" : "N";
return put(stringKey,stringValue);
}
#Override
public synchronized String put (String key, String value)
{
if (key == null)
return null;
if (value == null)
return remove(key);
//
int index = m_keys.indexOf(key);
if (index != -1)
return m_values.set(index, value);
m_keys.add(key);
m_values.add(value);
return null;
} // put
}
Both methods are used by this app a lot, I can't change the name of any and I can't delete put(Object key, Object value) method, any ideas how I can fix this?
#Aris_Kortex well firts of all, VO is used a LOT, to create the UImodel of this application and the constructor of VO is this:
public VO (Map<String,String> map)
{
this();
Iterator<String> it = map.keySet().iterator();
while (it.hasNext())
{
Object key = it.next().toString();
Object value = map.get(key);
put (key, value);
}
} // VO
/** Base SerVersion */
private static final long serialVersionUID = 8683452581122892189L;
/** Keys */
private ArrayList<String> m_keys;
/** Values */
private ArrayList<String> m_values;
/** Embedded VOs */
protected ArrayList<VO> p_vos = null;
then i am affraid i can't measure the impact of changing something here...i need to create a package of this proyect that i refactoriced because before was a mess..but maven throw me that error...
Given 2 Class objects how can I get the Class object of a Map?
For example, assume I have:
Class keyClass = Long.class;
Class valueClass = String.class;
How can I get the Class object ofMap<Long,String>?
There is no such class of Map<Long, String>. What you want is Map.class. (or HashMap.class, etc)
Map<String, Integer> map1 = new HashMap<>();
Map<Long, String> map2 = new HashMap<>();
System.out.println(map1.getClass().equals(map2.getClass()));
The result is true.
Map<Long, String> is not a class, but it is a type, ParameterizedType to be exact, sadly java code for constructing them is private, but they are 2 ways to get it, more dynamic way is to implement that interface:
final class ParameterizedTypeImpl implements ParameterizedType {
private final Type[] actualTypeArguments;
private final Class rawType;
#Nullable private final Type ownerType;
ParameterizedTypeImpl(Class rawType, Type[] actualTypeArguments, #Nullable Type ownerType) {
this.actualTypeArguments = actualTypeArguments.clone();
this.rawType = rawType;
if ((ownerType != null) || (rawType.getDeclaringClass() == null)) {
this.ownerType = ownerType;
}
else {
Class declaringClass = rawType.getDeclaringClass();
if (Modifier.isStatic(rawType.getModifiers())) {
this.ownerType = declaringClass;
}
else {
TypeVariable[] typeParameters = declaringClass.getTypeParameters();
if (typeParameters.length == 0) {
this.ownerType = declaringClass;
}
else {
this.ownerType = new ParameterizedTypeImpl(declaringClass, typeParameters, null);
}
}
}
}
#Override
public Type[] getActualTypeArguments() { return this.actualTypeArguments.clone(); }
#Override
public Class getRawType() { return this.rawType; }
#Nullable #Override
public Type getOwnerType() { return this.ownerType; }
#Override public boolean equals(Object o) {
if (o instanceof ParameterizedType) {
ParameterizedType that = (ParameterizedType) o;
if (this == that) return true;
Type thatOwner = that.getOwnerType();
Type thatRawType = that.getRawType();
return Objects.equals(this.ownerType, thatOwner) && Objects.equals(this.rawType, thatRawType) && Arrays.equals(this.actualTypeArguments, that.getActualTypeArguments());
}
return false;
}
#Override
public int hashCode() {
return Arrays.hashCode(this.actualTypeArguments) ^ Objects.hashCode(this.ownerType) ^ Objects.hashCode(this.rawType);
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder(256);
if (this.ownerType != null) {
sb.append(this.ownerType.getTypeName());
sb.append("$");
if (this.ownerType instanceof ParameterizedTypeImpl) {
sb.append(this.rawType.getName().replace(((ParameterizedTypeImpl) this.ownerType).rawType.getName() + "$", ""));
}
else {
sb.append(this.rawType.getSimpleName());
}
}
else {
sb.append(this.rawType.getName());
}
StringJoiner joiner = new StringJoiner(", ", "<", ">");
joiner.setEmptyValue("");
for (Type type : this.actualTypeArguments) {
joiner.add(type.getTypeName());
}
sb.append(joiner.toString());
return sb.toString();
}
}
And then you can just do new ParameterizedTypeImpl(Map.class, new Type[]{String.class, Long.class}, null) note that it would be a good practice to make this class not visible to others and just create some factory methods.
Other less dynamic way is to use type tokens like in gson:
public class TypeToken<T> {
final Type type;
protected TypeToken() {
this.type = this.getClass().getGenericSuperclass();
}
public final Type getType() { return this.type; }
#Override public final int hashCode() { return this.type.hashCode(); }
#Override public final boolean equals(Object o) { return (o instanceof TypeToken<?>) && this.type.equals(((TypeToken<?>) o).type); }
#Override public final String toString() { return this.type.toString(); }
}
and then new TypeToken<Map<String, Long>>{}.getType(); - types needs to be provided at compile time.
There should be some libraries that provide both this methods, but I don't know any right now as I needed to make my own to also support parsing from string.
So, what I have here is a Red Black Tree implementation of a Dictionary (aka Map). I am trying to find and return the corresponding key given a value using the getKey() method. I am trying to achieve this using only Java APIs. If you know more than one way to do it, please list a few. Also, if there is a problem with any of the my method definitions please inform me of the proper way to do it.
TreeMap<K,V> tree;
public RedBlackTree() {
tree = new TreeMap<K,V>();
}
public boolean contains(K key) {
return tree.containsKey(key);
}
public boolean add(K key, V value) {
tree.put(key, value);
return true;
}
public boolean delete(K key) {
if(!contains(key))
return false;
tree.remove(key);
return true;
}
public V getValue(K key) {
V ret = tree.get(key);
return ret;
}
public K getKey(V value) {
//HOW DO I DO THIS?
}
public int size() {
return tree.size();
}
public boolean isFull() {
return false;
}
public boolean isEmpty() {
return tree.size() == 0;
}
public void clear() {
tree.clear();
}
public Iterator<K> keys() {
return tree.keySet().iterator();
}
public Iterator<V> values() {
return tree.values().iterator();
}
}
Note that there may be several keys for the same value:
TreeMap<Object, Object> tree = new TreeMap();
tree.put(1, 1);
tree.put(2, 1);
this is how to get the keys for the specified value with Java 8
Object value = 1;
Object[] keys = tree.entrySet().stream().filter(e -> value.equals(e.getValue()))
.map(e -> e.getKey()).toArray();
Try this
#SuppressWarnings("unchecked")
public K getKey(V value) {
for (Map.Entry entry:tree.entrySet()){
if (entry.getValue().equals(value))
return (K) entry.getKey();
}
return null;
}
This question already has answers here:
HashMap to return default value for non-found keys?
(16 answers)
Closed 9 years ago.
While using Map as a function argument, only values for 3 keys are populated. However when this function is invoked in another function, the user populates values for initial 2 keys and he does not require 3rd key to be assigned with any value. However if 3rd key is not assigned any value then, the 3rd key is display null value.
Is there any way to avoid this. if user does not assign any value to 3rd key, it must be empty instead of null value.
public String setMapValues(Map<String,String> testMap) throws Exception
{
String str="";
str= testMap.get("a");
str+=testMap.get("b");
str+=testMap.get("c");
info(str);
return str;
}
public void run() throws Exception
{
LinkedHashMap<String,String> myMap = new LinkedHashMap<String,String>();
myMap.put("a", "James");
myMap.put("b", "Bond");
this.setMapValues(myMap);
}
The function calls displays JamesBondnull as the output, instead it should only display JamesBond as the output by ignoring/skipping the null at the end.
You can use a function like
static String nullAsEmpty(Object o) {
return o == null ? "" : o.toString();
}
public String setMapValues(Map<String,String> testMap) {
String str = nullAsEmpty(testMap.get("a")) +
nullAsEmpty(testMap.get("b")) +
nullAsEmpty(testMap.get("c"));
info(str);
return str;
}
How about:
String temp = testMap.get("c");
str+= (temp == null : "" : temp);
You can implement your version of Map:
import java.util.HashMap;
class MyMap<K, V> extends HashMap<K, V> {
#Override
public V get(Object key) {
V val = super.get(key);
if (val != null) {
return val;
} else {
return "";
}
}
}
Then just use MyMap instead of Map
Or init your map with default values, if you know all keys which could be null
Map getInstance(){
Map<String,String> myMap = new LinkedHashMap<String,String>();
myMap.put("a", "");
myMap.put("b", "");
myMap.put("b", "");
return myMap;
}
By putting duplicate keys the old values are replaced by the new ones.
To be complete:
If you use Vadchens answer - which is better - you can do two things:
Extends your map by setting generic value-parameter directly to String
class MySecMap<K> extends LinkedHashMap<K, String>{
#Override
public String get(Object key) {
String val = super.get(key);
if (val != null) {
return val;
} else {
return "";
}
}
}
Or create a class with an extra interface and a default-value-provider:
interface IDefaultValueProvider<V>{
V getDefaultValue();
}
class MyMap<K, V, D extends IDefaultValueProvider<V>> extends LinkedHashMap<K, V>{
private IDefaultValueProvider<V> provider;
public MyMap(IDefaultValueProvider<V> p){
super();
provider = p;
}
#Override
public V get(Object key) {
V val = super.get(key);
if (val != null) {
return val;
} else {
return this.provider.getDefaultValue();
}
}
}