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

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);

Related

How to make an immutable map given a map using Guava?

Given a Map, how can I make an immutable map using Guava? I know one way through Collections.unmodifiableMap but is there any other way using Guava?
Map<String, String> realMap = Maps.newHashMap();
realMap.put("A", "B");
// any other alternative?
Map<String, String> unmodifiableMap = Collections.unmodifiableMap(realMap);
I am populating my realMap with some entries and then I need to make it Immutable so that no one can modify it. I am just trying to see if there is any alternative using Guava? I did some search but I cannot find it.
You're looking for ImmutableMap.copyOf():
ImmutableMap<String, String> immutableMap = ImmutableMap.copyOf(realMap);
Keep in mind that, as opposed to unmodifiableMap() which only creates a wrapper to its argument, this actually copies it to a new map. That can mean a slight performance hit, but it also means there's no possibility of the map being modified accidentally through realMap.

Putting element into HashMap with Map interface

I'm trying Kotlin and I've encountered a small problem that I can't resolve.
When I have the following construction I can put elements into the map:
val map = HashMap<String, String>()
map["asd"] = "s"
map.put("34", "354")
However when I create a map with the Map interface I can only read them, what I'm doing wrong ?
val map: Map<String, String> = HashMap<String, String>();
map.put("24", "34") //error
map["23"] = "23" //error
Or maybe I'm confusing something about interfaces in Kotlin ?
In the first example map gets the type of HashMap,
in the second example you cast it to the Interface Map.
Map is a readonly map, there is no put/set, see here
In order to be able to edit the map, you should use MutableMap
When working with kotlin collections, one important consideration is that, kotlin categorizes its collections as mutable and immutable. this is in contrast to java, where no such categorization exists.
In kotlin for most collections you have a base interface which only supports read-only methods. In your case Map<K,V is an example of that, from the docs
Methods in this interface support only read-only access to the map;
read-write access is supported through the MutableMap interface.
this is the reason for error when you try to modify the map after val map: Map<String, String> = HashMap<String, String>();, even though the actual object is of type HashMap<String,String>, but the map reference is of type Map<String,String>, which will only provide read only operation.
Now if you use a class which implements MutableMap<K,V> then you can put values in map as well. this is the case with val map = HashMap<String, String>(), since here type of map is HashMap<K,V>, which extends MutableMap<K,V> and hence is mutable.

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?

Using keySet() method then changing the Set to a String Array? 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

Collection for storing objects with date

I have some objects with Date parameters. What collection will be best for storing them and later querying for object/objects with particular date ? (like given as a String or java.util.Date format) ?
EDIT:
I was trying to use TofuBear's solution, but cannot make it work. let's say I am calling my function (which returns Map) with a list of objects, and Date object. What next ? I was trying different methods but everything is just bloody red from NetBeans's errors:
public Map<Date, List<Person>> createDateList(Date date, List<Person> list){
Map<Date, List<Person>> map = null;
}
This however does not solve problem of querying, cuz I'm just creating a map with one object. I need to have a list of all objects (which have Date field) and their dates in a map. Am I thinking correctly ?
Probably a Map<Date, WhateverTypeYouWant> or Map<Date, List<WhateverTypeYouWant>> if there are multpile values with the same date.
Then you would add them something like this:
map.put(object.getDate(), object);
Edit based on the comment:
For the List version I use something like this (untested from memory... but pretty sure it is right):
List<WhateverTypeYouWant> list;
list = map.get(object.getDate())
if(list == null)
{
list = new ArrayList<WhateverTypeYouWant>();
map.put(object.getDate(), list);
}
list.add(object);
Sounds like a Map<Date, YourObject> (or Map<String, YourObject> if you prefer so) would do the job.
Maps come in different flavours, the most generally used is HashMap.
Map<Date, Other>, as others have said, but if you are interested in more than getting an entry that matches a given date exactly then you would want to look into using a NavigableMap. A navigable map will allow you to get entries that are close to what you are searching for if nothing matches exactly.
If you use Map<Date, SomeObject> like other have suggested, you will only be able to do exact searches and in case you change Date inside SomeObject you'll need to manually update the Map. Even more work if you choose to use Map<Date, List<SomeObject>>.
Instead use List<SomeObject> and use Collections.binarySearch(). This requires Collection to be sorted and you need to write custom java.util.Comparator.
private class SomeObjectComparator implements Comparator<SomeObject> {
#Override
public int compare(SomeObject o1, SomeObject o2) {
// this breaks equality rule for Set
// do not use in Sets
return o1.date.compareTo(o2.date);
}
}
then use it like this (preferably wrap it in helper method):
List<SomeObject> someList = new ArrayList<SomeObject>
Comparator comparator = new SomeObjectComparator();
Collections.sort(someList, comparator);
int resultIndex = Collections.binarySearch(someList, someSearchedObject, comparator)
Given this comparator, binarySearch() will only search by Date not by other properties of SomeObject.
Also look for meaning of resultIndex in Collections.binarySearch()
In side the collection API stored the reference addresses of the attribute (of like list, linked List ) for which required the boxing on primitive data type element, in its correspondence Wrapper class type object and that one object are automatically up-castes to Object type class (Object class is the Super class of every Class) And this reference object can pass for any other program (Inside same or different Package) with the Multiple Resection on the OWN date (Like only reading, removing, Updating, Reading only one time, adding more element inside list) according with requirement. for which reference object is only usefull to avoid multiple problems.

Categories

Resources