Using keySet() method then changing the Set to a String Array? Java - java

So this should be really simple since I know it's possible (I just don't understand 'Set' very much).
So basically there is this TreeMap, let's call it aTree. So I need to do something like:
somethingHereProbably = aTree.keySet();
somethingHereProbably.toStringArray();

You can do
Map<String, Object> map = ...
String[] strings = map.keySet().toArray(new String[map.size()]);
This works for any kind of map, including TreeMap

Related

Using the same HashMapM<String,....> for String and array of String (String[])

I have some attributes that are of the type String, and the type "ArrayString" (String[]). How can I put then in the same HashMap?
Example:
String data;
String[] array;
... // Initialize and put the values in attributes
HashMap <String, *> hm = new HashMap<String, *> // * -> it's what i want
hm.put ("data", data);
hm.put("array", array);
Which value, or class, must be in *?
Personally, I'd go about it a different way - always store the values as String[], and if you have a single value just store it in an array with a single element). It would make your code considerably simpler.
If you absolutely must mix Strings and String[]s, you can only use Object as the value type (i.e., HashMap<String, Object>, and will have to use runtime type identification in your code.
you can use
HashMap<String, List<String>>
instead to accomplish your goals. If this doesn't suit you please provide more context and I'd be glad to help

Can I define a hashmap differently to it's declaration

What I would like to do is have a map that actually holds values as one thing, but is declared as another e.g. actually hold the value as String, but put/get will use Integer...
Map<String,String> map = new HashMap<String,String>();
I can use this map with
map.put("A","1");
String ret = map.get("A");
but this will get me a String, and I need to 'put' in a String too.
What I would like is for the put/get methods to accept an Integer value (but the map still stores ...
map.put("A",1);
Integer ret = map.get("A");
How can I achieve this?
N.B. this isn't exclusively for String/Integer conversion, but just conversion between any types.
Thanks.
You can use Object as the value type. It can store String, Integer, Double, for that matter almost anything. But you need to be very careful when using Object because you'll have to cast each value you get from the map accordingly(else you'll always get a ClassCastException).
Map<String, Object> map = new HashMap<String, Object>();
FYI, I do not recommended you to use this. Instead be sure what your Map has to hold and have the value type accordingly.
Simply
Map<String,Integer> map = new HashMap<String,Integer>();
You can (but not SHOULD use, really) this critter: https://gist.github.com/eltabo/8953176. Really... it's evil.
Only for educational purpose.
Why should someone want to store a value in a different representation than the value is made out of? You still can create a string out of an integer and reverse after obtaining it from the map, but what is your advantage?

Change from CharSequence to String for Set<CharSequence> & Map<CharSequence, Object>

Scenario 1:
I got a Set<CharSequence> from somewhere, which means I have no control on how this set has been created.
Set<CharSequence> dataSet = GET_DATA_SET();
I would like to convert the data from Set<CharSequence> to Set<String>. Is there an efficient way to do this conversion without iterate over each element?
Scenario 2:
I also get another data as a HashMap type (Again, I have no control on the creation part for this Map data) :
Map<CharSequence, Car> dataMap = GET_DATA_MAP();
Is there an efficient way to convert this Map to Map<String, Car> without iteration ?
Like Eng.Fouad is mentioned not all CharSequence is String.
So we must invoke toString() method.
Just use:
Set<CharSequence> dataSet = new HashSet<CharSequence>(Arrays.asList("a","b"));
Set<String> output = new HashSet<String>();
for(CharSequence c : dataSet){
output.add(c.toString());
}
Pretty simple and clear
If you are sure that the object are Strings, then you can do a (unchecked) cast, with the risk that if you assumption becomes wrong, you will get a ClassCastException:
Map<CharSequence, Object> dataMap = new HashMap<>();
#SuppressWarnings("rawtypes")
Map untypedDataMap = dataMap;
#SuppressWarnings("unchecked")
Map<String, Object> stringDataMap = untypedDataMap;
Note that this is quite risky, specially if the Map comes from an external library. I would loop over the Map to convert each CharSequence to a String.
Your problem is based on the asumption that the loop would be inefficient, but are you sure of this? And how would it be a problem in your case? Modern compiler and hardware are very efficient, it is possible that you don't even notice a difference with a loop.
Try
Set<String> dataSet = (Set<String>)(Set)GET_DATA_SET();
You can use this wildcards:
Set<? extends CharSequence> dataSet;
Map<? extends CharSequence, Car> dataMap;
It's safe and proper. But you must remember that your method may return objects, which you will not be able to cast to some heirs of CharSequence
Not sure if it is possible to do without iteration in java core. Perhaps, you can use Guava to do that. Take a look at Lists.transform and Collections2.transform
If you are sure there is no non-string objects, simply cast your object to Set<String> using
(Set<String>)((Object)dataSet);
Example:
(Set<String>)((Object)new HashSet<CharSequence>()));
But this is very dirty and unsafe trick.
Edit:
As mentioned by #LaurentG, you can do
(Set<String>)((Set)dataSet);

Java - getting value from an array using string

I need to make an int array using Strings instead of ints.
EX: int["number2"] = 0; instead of int[2] = 0;
Does anyone know how to do this?
Thanks for your time.
you could use a HashMap - see here for more info!
Java doesn't support associative arrays, but you could use a HashMap:
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("key1", 25);
map.put("key2", 4589);
map.get("key1") will return 25.
You are not looking for an array but for an associative array.
In Java, in practice, every class that implements Map can be used as an associative container, since they can map keys to values (TreeMap<K,V>, HashMap<K,V>, and so on)
This syntax looks very like a map in Groovy, In Java, you could use something like a Map<String, Integer>.

Comparing TreeMap contents gives incorrect answer

I use a TreeMap as a 'key' inside another TreeMap
ie
TreeMap<TreeMap<String, String>, Object>
In my code 'object' is a personal construct, but for this intance I have used a string.
I have created a pair of TreeMaps to test the TreeMap.CompareTo() and TreeMap.HashCode() methods. this starts with the following...
public class TreeMapTest
public void testTreeMap()
{
TreeMap<String, String> first = new TreeMap<String, String>();
TreeMap<String, String> second = new TreeMap<String, String>();
first.put("one", "une");
first.put("two", "deux");
first.put("three", "trois");
second.put("une", "one");
second.put("deux", "two");
second.put("trois", "three");
TreeMap<TreeMap<String, String>, String> english = new TreeMap<TreeMap<String, String>, String>();
TreeMap<TreeMap<String, String>, String> french = new TreeMap<TreeMap<String, String>, String>();
english.put(first, "english");
french.put(second, "french");
From here I now call the the english item to see if it contains the key
if (english.containsKey(second))
{
System.out.println("english contains the key");
//throws error of ClassCastException: Java.util.TreeMap cannot be cast to
//Java.Lang.Comparable, reading the docs suggests this is the feature if the key is
//not of a supported type.
//this error does not occur if I use a HashMap structure for all maps, why is
//this key type supported for one map structure but not another?
}
However I should note that both HashMap and TreeMap point to the same HashCode() method in the AbstractMap parent.
My first thought was to convert my TreeMap to a HashMap, but this seemed a bit soppy! So I decided to apply the hashCode() method to the 2 treemap objects.
int hc1 = first.hashCode();
int hc2 = second.hashCode();
if(hc1 == hc2)
{
systom.out.printline("values are equal " + hc1 + " " + hc2);
}
prints the following
values are equal 3877431 & 3877431
For me the hashcode should be different as the key values are different, I can't find details on the implementation difference of the hashCode() method between HashMap and TreeMap.
Please not the following.
changing the Keys only to HashMap doesn't stop the ClassCastException error. Changing all the maps to a HashMap does. so there is something with the containsKey() method in TreeMap that isn't working properly, or I have missunderstood - can anyone explain what?
The section where I get the hashCode of the first and second map objects always produces the same output (no matter if I use a Hash or Tree map here) However the if(english.ContainsKey(second)) doesn't print any message when HashMaps are used, so there is obviously something in the HashMap implementation that is different for the compareTo() method.
My principle questions are.
Where can I find details of the types of keys for use in TreeMap objects (to prevent future 'ClassCastException' errors).
If I can't use a certain type of object as a key, why am I allowed to insert it as a key into the TreeMap in the first place? (surely if I can insert it I should be able to check if the key exists?)
Can anyone suggest another construct that has ordered inster / retrieval to replace my TreeMap key objects?
Or have I potentially found strange behaviour. From my understanding I should be able to do a drop in replacement of TreeMap for HashMap, or have I stumbled upon a fringe scenario?
Thanks in advance for your comments.
David.
ps. the problem isn't a problem in my code as I use a personal utility to create a hash that becomes dependent on the Key and Value pairs (ie I calculate key hash values differently to value hash values... sorry that if is a confusing sentence!) I assume that the hashCode method just sums all the values together without considering if a item is a key or a value.
pps. I'm not sure if this is a good question or not, any pointers on how to improve it?
Edit.
from the responses people seem to think I'm doing some sort of fancy language dictionary stuff, not a surprise from my example, so sorry for that. I used this as an example as it came easily to my brain, was quick to write and demonstrated my question.
The real problem is as follows.
I'm accessing a legacy DB structure, and it doesn't talk nicely to anything (result sets aren't forward and reverse readable etc). So I grab the data and create objects from them.
The smallest object represents a single row in a table (this is the object that in the above example I have used a string value 'english' or 'french' for.
I have a collection of these rowObjects, each row has an obvious key (this is the TreeMap that points to the related rowObject).
i don't know if that makes things any clearer!
Edit 2.
I feel I need to elaborate a little further as to my choice of originaly using
hashMap<HashMap<String,string>, dataObject>
for my data structure, then converting to TreeMap to gain an ordered view.
In edit 1 I said that the legacy DB doesn't play nicely (this is an issue with the JDBC.ODBC I suspect, and I'm not about to acquire a JDBC to communicate with the DB). The truth is I apply some modifications to the data as as I create my java 'dataObject'. This means that although the DB may spit out the results in ascending or descending order, I have no way of knowing what order they are inserted into my dataObject. Using a likedHashMap seems like a nice solution (see duffymo's suggestion) but I later need to extract the data in an ordered fashion, not just consecutively (LinkedHashMap only preserves insertion order), and I'm not inclined to mess around with ordering everything and making copies when I need to insert a new item in between 2 others, TreMap would do this for me... but if I create a specific object for the key it will simply contain a TreeMap as a member, and obviously I will then need to supply a compareTo and hashCode method. So why not just extent TreeMap (allthough Duffymo has a point about throwing that solution out)!
This is not a good idea. Map keys must be immutable to work properly, and yours are not.
What are you really trying to do? When I see people doing things like this with data structures, it makes me think that they really need an object but have forgotten that Java's an object-oriented language.
Looks like you want a crude dictionary to translate between languages. I'd create a LanguageLookup class that embedded those Maps and provide some methods to make it easier for users to interact with it. Better abstraction and encapsulation, more information hiding. Those should be your design objectives. Think about how to add other languages besides English and French so you can use it in other contexts.
public class LanguageLookup {
private Map<String, String> dictionary;
public LanguageLookup(Map<String, String> words) {
this.dictionary = ((words == null) ? new HashMap<String, String>() : new HashMap<String, String>(words));
}
public String lookup(String from) {
return this.dictionary.get(from);
}
public boolean hasWord(String word) {
return this.dictionary.containsKey(word);
}
}
In your case, it looks like you want to translate an English word to French and then see if the French dictionary contains that word:
Map<String, String> englishToFrenchWords = new HashMap<String, String>();
englishToFrenchWords.put("one", "une");
Map<String, String> frenchToEnglishWords = new HashMap<String, String>();
frenchToEnglishWords.put("une", "one");
LanguageLookup englishToFrench = new LanguageLookup(englishToFrenchWords);
LanguageLookup frenchToEnglish = new LanguageLookup(frenchToEnglishWords);
String french = englishToFrench.lookup("one");
boolean hasUne = frenchToEnglish.hasWord(french);
Your TreeMap is not Comparable so you can't add it to a SortedMap and its not immutable so you can't add it to a HashMap. What you could use an IdentityMap but suspect an EnumMap is a better choice.
enum Language { ENGLISH, FRENCH }
Map<Language, Map<Language, Map<String, String>>> dictionaries =
new EnumMap<>(Language.class);
Map<Language, Map<String, String>> fromEnglishMap = new EnumMap<>(Language.class);
dictionaries.put(Language.ENGLISH, fromEnglishMap);
fromEnglishMap.put(Language.FRENCH, first);
Map<Language, Map<String, String>> fromFrenchMap = new EnumMap<>(Language.class);
dictionaries.put(Language.FRENCH, fromFrenchMap);
fromEnglishMap.put(Language.ENGLISH, second);
Map<String, String> fromEnglishToFrench= dictionaries.get(Language.ENGLISH)
.get(Language.FRENCH);
To the problem why Hashmap works and Treemap does not:
A Treemap is a "sorted map", meaning that the entries are sorted according to the key. This means that the key must be comparable, by implementing the Comparable interface. Maps usually do NOT implement this, and I would highly suggest you do not create a custom type to add this feature. As duffymo mentions, using maps as keys is a BAD idea.

Categories

Resources