I want to use Java collection to find the words in the list that begin with the startup letter:
example:
TreeMap<String, Double> tm = new TreeMap<String, Double>();
// Put elements to the map
tm.put("Zara", new Double(3434.34));
tm.put("Mahnaz", new Double(123.22));
tm.put("Ayan", new Double(1378.00));
tm.put("Daisy", new Double(99.22));
tm.put("Qadir", new Double(-19.08));
Toast.makeText(getApplicationContext(), ""+tm.get("Zar"),Toast.LENGTH_SHORT).show();
in this case it will show null. But what i want to do is to show all the words that start with that letter. How can i do this? Thanks in advance
Since TreeMap is a NavigableMap, it is computationally cheap to iterate the map starting from a given key:
String prefix = "Zar";
for (String person::tm.tailMap(prefix).keySet()) {
if (person.startsWith(prefix)) {...}
}
There are a few choices:
If you always go from the first three characters then do a multimap - Map<String, List<Data>> Where Data contains String name and double double and the key is the first three letters of all the names.
You can scan through the TreeMap and because it is sorted at least you know you can stop once you get past Zar - but this will still be inefficient.
You can use a database (embed a Derby Database for example) and use the indexing/search/query functionality of the database.
You can build your own tree structure branching on each character in the word. Then root->z->a->r would then give you every word beginning with zar. root->b->o would give you every word beginning with bo, etc.
TreeMap<String, Double> tm = new TreeMap<String, Double>();
//...add values.
//get all keys
Set<String> keys = tm.keySet();
Set<String> result = new HashSet<String>();
for(String key : keys){
//check the beginning of the keys
if(key.startsWith("Zar"){
result.put(key);
}
}
//get the values for your collected keys
for(String key : result){
double value = tm.get(key);
}
Just reading when to use what collection will only help you if you run across the exact same situation in your code. If you don't understand the roots of why a given data structure is good for a problem, you won't be able to apply this to your own code.
this link may help you
You only have to Iterate over the list and check if the key starts with the given String.
Example:
for (String elem : tm.keySet()) {
if(elem.startsWith("Zar")) {
System.out.println(elem);
}
}
output:
Zara
and if you want to ignore the case:
if(elem.toLowerCase().startsWith("zar".toLowerCase()))
So How can you achieve this?
First find all the keys of HashMap by
tm.keySet()
then use iterator on keys and match with the string.See example below
String abc = "Zar";
HashMap s = new HashMap();
s.put("Zara", new Double(1.0));
Set x =s.keySet();
Iterator iter = x.iterator();
while (iter.hasNext()) {
String key = iter.next().toString();
if(key.startsWith(abc)){
System.out.println(s.get(key));
}
}
Related
I have to compare two Excel files (with different data) and create two new Excel tables:
Table 1 contains all matching entries
Table 2 contains all entries that not match
Therefore I iterate over both Excel files and store the matching entries in a LinkedHashMap. In a second LinkedHashMap I store all entries from the Excel file. With this two Maps I want to identify the delta.
To identify the delta I compare both lists and now want to remove all entries from the complete list, if the entry is already in the list with the matching ones.
I tried different solutions - all with the result that the code is running but never an entry is really removed. Can anyone help please?
Heres my code:
// This code fills both Maps
LinkedHashMap<String, String> liste_matches = new LinkedHashMap<String, String> ();
LinkedHashMap<String, String> liste_complete = new LinkedHashMap<String, String> ();
while(worksheet1.getLastRowNum() >= j){
liste_complete.put(String.valueOf(worksheet1.getRow(j).getCell(18)), "");
// Counter for loop, loops trough Telekom datasets
int i = 1;
while(worksheet2.getLastRowNum() >= i)
{
if(String.valueOf(worksheet1.getRow(j).getCell(18)).equals(String.valueOf(worksheet2.getRow(i).getCell(9))))
{
if(!liste_matches.containsKey(String.valueOf(worksheet1.getRow(j).getCell(18)))){
liste_matches.put(String.valueOf(worksheet1.getRow(j).getCell(18)), "");
}
}
}
// build Excel table
}
This is my code I used to compare both lists and remove all entries from liste_complete that are already in liste_matches.
I first tried this (I inserted the ArrayList for my second try...). It's running but without any effect to the list.
ArrayList list = new ArrayList();
for(Map.Entry<String,String> keyDelta : liste_complete.entrySet())
{
for(Map.Entry<String,String> key : liste_matches.entrySet()){
if(keyDelta.equals(key)){
liste_complete.remove(keyDelta);
list.add(entry.getValue());
}
}
}
Afterwards I tried this but also without any effect to the List:
for(int c = 0; c < list.size(); c++)
{
String str = list.get(c);
liste_complete.remove(str);
}
I found this solution in StackOverflow, but that returns java.lang.IllegalStateException
Iterator<Map.Entry<String,String>> iter = liste_complete.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<String,String> entry = iter.next();
for(Map.Entry<String,String> key : liste_matches.entrySet()){
if(key.getValue().equalsIgnoreCase(entry.getValue())){
iter.remove();
}
}
}
AFAIK you can't remove element from a list you're iterating on.
I suggest you 2 solutions:
iterate on your lists to check for matching keys and store the match in the third list; then iterate on the third list and remove from liste_complete
refactor the first piece of code of your question so that you store in one list the matching values and in the other the non-matching. Pseudo code could be:
for worksheet1 row
for worksheet2 row
if(match)
liste_matches.add(...)
else
liste_non_matches.add(...)
In this way you do not have to remove elements afterwards.
Thanks a lot for your hints.
I already debugged the code but didn't understand the problem - I think it really was a problem of the complex input data.
I did not compare the keys via key.getKey() but only with key and that seems to cause problems in the comparison. Anyway, my code runs with this snippet:
for(Map.Entry<String,String> keyDelta : liste_Complete.entrySet()){
if(!liste.containsKey(keyDelta.getKey())){
delta_liste.put(String.valueOf(keyDelta), "");
}
}
I want to create a hashmap defined as HashMap<Character,ArrayList<String>>.
What I am trying to do is to read a set of strings which I am reading into a list.
From this list I want to generate this hashmap.
So if strings are something like this
Andy,Aman,Rocky,Ravi,Nick etc.
Map should be like
A->[Andy,Aman]
R->[Rocky,Ravi]
N->Nick
What I have tried is something like this
ArrayList<String> xlist= new ArrayList<String>();
ArrayList<String> list = new ArrayList<String>();
HashMap<Character,ArrayList<String>> h = new HashMap<Character,ArrayList<String>>();
Scanner s = new Scanner(System.in);
for(String sin : list){
Character x =sin.charAt(0);
//System.out.println(sin.charAt(0));
if(h.containsKey(x)){
h.get(x).add(sin);
//xlist.clear();
//xlist = h.get(x);
//xlist.add(sin);
//h.put(x,xlist.clone());
}
else{
xlist.clear();
xlist.add(sin);
h.put(x,xlist);
}
}
When I print the hashmap, I get this
{A=[Ravi, Rocky], R=[Ravi, Rocky], N=[Ravi, Rocky]}
I understand , that all the lists in values are being reflected from same copy of list, but I don't know , how to resolve it.
If you don't want to rewrite the loop, you can just change your last line within the else block so you won't change content of map on every iteration:
h.put(x,new ArrayList<String>(Arrays.asList(sin)));
You can also do it using Java 8 Streams which makes it much shorter:
Map<Character, List<String>> map = list.stream().collect(Collectors.groupingBy(d -> d.charAt(0)));
If you want to preserve the order of keys you can use it with LinkedHashMap:
Map<Character, List<String>> map = list.stream().collect(Collectors.groupingBy(d->d.charAt(0), LinkedHashMap::new, Collectors.toList()));
xlist is always the same list, even after you've put it in your hashmap. Whenever you hit a new letter, you clear every list in your hashmap, and add the current word to every list, because they're all the same list.
I'd rewrite your loop as:
for(String sin : list){
Character x =sin.charAt(0);
if(!h.containsKey(x)){
h.put(x, new ArrayList<String>());
}
h.get(x).add(sin);
}
I am very new to java had a question regarding returning the dictionary with the help of hashmap. The problem is I have string array let say with four names and I have to iterate and differentiate name according to the string length and if the key does not match I have to create other list and if it matches I have to simply append the string.
Basically the expected output should be like this
3:kel
4:john,aron
5:sonny
6:abraham
I tried little bit but stuck code looks like this
public static void main(String arg[])
{
HashMap<integer, ArrayList<String>> map = new HashMap<integer, ArrayList<String>>();
ArrayList<String> namelist = new ArrayList<String>();
obj.add("john");
obj.add("kel");
obj.add("abraham");
obj.add("sonny");
obj.add("aron");
map.put(3, namelist);
for (int i = 0; i < namelist.size(); i++) {
String element = namelist[i];
String nextElement = elements[i+1];
}
}
Your datatypes on the HashMap are not ideal. You want HasMap<Integer, List<String>>, although you could use String as a key if you call toString on the integer length of the name before using it as a key. Then, loop through the obj list and check if the length of the string you're on (obj[i].length()) exists in map using map.containsKey(obj[i].length()). If it does exist, you will map.get(obj[i].length()).add(obj[i]), and if it doesn't you will create a new ArrayList containing obj[i] and use the .put method on the HashMap to add it.
In the code you posted, first appears to not be defined.
I would rename obj to nameList, or something more descriptive. It's not an object.
Java 8's streaming capabilities offer a pretty elegant one-liner for this with the built in groupingBy collector:
Map<Integer, List<String>> map =
obj.stream().collect(Collectors.groupingBy(String::length));
What I have is a HashMap<String, ArrayList<String>> called examList. What I want to use it for is to save grades of each course a person is attending. So key for this HashMap is couresID, and value is a ArrayList of all grades (exam attempts) this person has made.
The problem is I know how to work with array lists and hashmaps normally, but I'm not sure how to even begin with this example. So how would I, or example, add something to ArrayList inside HashMap?
You could either use the Google Guava library, which has implementations for Multi-Value-Maps (Apache Commons Collections has also implementations, but without generics).
However, if you don't want to use an external lib, then you would do something like this:
if (map.get(id) == null) { //gets the value for an id)
map.put(id, new ArrayList<String>()); //no ArrayList assigned, create new ArrayList
map.get(id).add(value); //adds value to list.
String courseID = "Comp-101";
List<String> scores = new ArrayList<String> ();
scores.add("100");
scores.add("90");
scores.add("80");
scores.add("97");
Map<String, ArrayList<String>> myMap = new HashMap<String, ArrayList<String>>();
myMap.put(courseID, scores);
Hope this helps!
First create HashMap.
HashMap> mapList = new HashMap>();
Get value from HashMap against your input key.
ArrayList arrayList = mapList.get(key);
Add value to arraylist.
arrayList.add(addvalue);
Then again put arraylist against that key value.
mapList.put(key,arrayList);
It will work.....
First you retreieve the value (given a key) and then you add a new element to it
ArrayList<String> grades = examList.get(courseId);
grades.add(aGrade);
Java 8+ has Map.compute for such cases:
examList.compute(courseId, (id, grades) ->
grades != null ? grades : new ArrayList<>())
.add(value);
First, you have to lookup the correct ArrayList in the HashMap:
ArrayList<String> myAList = theHashMap.get(courseID)
Then, add the new grade to the ArrayList:
myAList.add(newGrade)
Can also do this in Kotlin without using any external libraries.
var hashMap : HashMap<String, MutableList<String>> = HashMap()
if(hashMap.get(id) == null){
hashMap.put(id, mutableListOf<String>("yourString"))
} else{
hashMap.get(id)?.add("yourString")
}
HashMap<String, ArrayList<ObjectX>> objList = new HashMap<>();
if(objList.containsKey(key))
objList.get(key).add(Object1);
else
objList.put(key, new ArrayList<ObjectX>(Arrays.asList(Object1)));
How do I sort hash table elements alphabetically? For example, my elements are:
cijfercode, Zweeds, Doorloper, Kruizword, Crypto, Woordzoker
edit: I also got a solution for sorting the hashtable elements. Here is the solution:
java.util.Vector vec = new java.util.Vector(hashtableList.keySet());
Collections.sort(vec);
If these "elements" are keys you can store them in a TreeMap, which will produce a consistent order based on the natural ordering of the keys. Note you don't need to do much except create a new map with the old map passed to the constructor:
Map<String,?> map = ?
Map<String,?> orderedMap = new TreeMap<String,?>(map);
Then, iterate like normal:
for(String key : orderedMap.keys()){
}
If your "elements" are values, then you can insert them as keys into a TreeMap keeping track of the original keys, read the sorted order of values as before (basically creating an inverted index):
Map<?,String> map = ?
Map<String,List<?>> orderedVals = new TreeMap<String,List<?>>();
for(Entry<?,String> map : map.entrySet()){
List<?> keys = orderedVals.get(map.getValue());
if(keys == null){
keys = new ArrayList<?>();
orderedVals.put(map.getValue(), keys);
}
keys.add(map.getKey());
}
// now orderedVals has keys in sorted order
for(String val : orderedVals.keys()){
}
Of course, if you're not actually using anything related to the fact these things are in a "hashtable" (I read this as something implementing Map), then you can load up a List of your choosing, and sort it:
List<String> list = new ArrayList<String>(map.values()); // or use map.keys()
Collections.sort(list);
If you're not happy with the default sort order for String, feel free to write your own comparator:
Collections.sort(list, new Comparator<String>(){
public int compare(String left, String right){
return // your impl
}
});
compare must return a negative integer when the left comes first, 0 if left and right are the same, and a positive integer if right comes first.
Mark Elliot's idea is correct. I don't like the whole Map<?, List<?>> idea though; I've been far too spoilt on Guava. So here's a Guava version of the same idea:
SortedSetMultimap<String, ?> sorted = Multimaps.invertFrom(
Multimaps.forMap(map), TreeMultimap.create());
for (Map.Entry<String, ?> entry : sorted.entries()) {
// ...
}
This is, like, a third of the size of Mark's code. :-)
java.util.Vector vec =new java.util.Vector(hashtableList.keySet());
Collections.sort(vec);
Please check http://discuss.joelonsoftware.com/default.asp?joel.3.19588.13 for an interesting discussion on this.
Consider http://download.oracle.com/javase/1.4.2/docs/api/java/util/TreeMap.html too.