I have a List with about 20,000,000 entries. About 5,000,000 entries are unique. I need to iterate over my List, identify unique entries, and assign each an integer between 0 and 5,000,000.
Currently, I sequentially add each entry to a TreeSet, then figure out where it went using .headSet(). I imagine this is suboptimal.
while((nextline = wholefile.listIterator().next()) != null){
//sorted, unique, addition
keywords.add(nextline);
//hmmm, get index of element in TreeSet?
k_j = keywords.headSet(nextline).size();
}
Is there a way to get the location when I call .add() ?
I would simply use a counter and HashMap<Keyword, Integer>. For each keyword in the list, get its position from the map. If you get null, put the keyword in the map with the current counter value as value, and increment the counter.
I would do as follows:
Count the objects by populating a Map<YourObject, Integer>.
Go through this map and assign a sequence number to each key which maps to the value 1.
In code...
List<String> keywords = Arrays.asList("a", "b", "c", "a");
Map<String, Integer> counts = new HashMap<String, Integer>();
for (String str : keywords) {
if (!counts.containsKey(str))
counts.put(str, 0);
counts.put(str, counts.get(str) + 1);
}
int seq = 0;
for (String keyword : counts.keySet())
if (counts.get(keyword) == 1) // is unique?
System.out.println(keyword + " -> " + seq++); // assign id.
Related
I created a Map<Integer, ArrayList<String>> map and I would like to compare each value in map with one ArrayList<String> likeList and get key if they match. I will bring the key to use later.
I tried to run my code like this, but it doesn't work because it returns nothing:
for (int key : map.keySet()) {
if(map.get(key).equals(likeList)){
index = key;
Log.d("IndexN", String.valueOf(index));
}
}
Then, I tried this:
int index = 0;
for (Map.Entry<Integer, ArrayList<String>> entry : map.entrySet()) {
if(entry.getValue().equals(likeList)){
index = entry.getkey();
}
}
Do you have any idea?
Add a list of the key to store all match
List<Integer> indices = new ArrayList<>();
for (int key : map.keySet()) {
if (map.get(key).equals(likeList)) {
indices.add(key);
}
}
It does not return index when I try the code above.
From this comment, I understood that as soon as you find a match in the map, the index should be recorded and further processing should be stopped. In other words, either there is only one match of likeList in the map or you want to find the first match of likeList in the map. If yes, you need to break the loop as soon as the match is found (shown below).
for (int key : map.keySet()) {
if (map.get(key).equals(likeList)) {
Log.d("IndexN", String.valueOf(index));
break;
}
}
Note that this will give you the same value, each time you execute it, only when the map has only one match of likeList or the map is a LinkedHashMap. If it is a HashMap and it has more than one matches of likeList, you may get a different value each time you execute it because a HashMap does not guarantee the order of its entries.
However, if there can be multiple matches of likeList in the map and you want to log all the matches as well as get the list of the corresponding keys, you can do it as follows:
List<Integer> indexList = new ArrayList<>();
for (int key : map.keySet()) {
if (map.get(key).equals(likeList)) {
Log.d("IndexN", String.valueOf(index));
indexList.add(key);
}
}
// Display the list of corresponding keys
System.out.println(indexList);
I have two linked hashmap (key - String, value = String[]) which got the same size and the same keys in both linked hashmaps, I want to be able to compare values according to the key, verifying values on one linked hashmap are equals to the same values in the second linked hashmap (by key) or at least the other linked hashmap contains the values.
I am populating both of the linked hashmaps with keys and values and set it to different linked hash maps.
Example for hashmap:
Key - alert - Value (array of strings)
0 - Device_UID,Instance_UID,Configuration_Set_ID,Alert_UID
1 - a4daeccb-0115-430c-b516-ab7edf314d35,0a7938aa-9a01-437f-88ac-4b2927ed7665,96,61b68069-9de7-4b85-83cb-8d9f558e8ecb
2 - a4daeccb-0115-430c-b516-ab7edf314d35,0a7938aa-9a01-437f-88ac-4b2927ed7665,12,92757faa-bf6b-4aa3-ba6d-2e57b44f333c
3 - a4daeccb-0115-430c-b516-ab7edf314d35,0a7938aa-9a01-437f-88ac-4b2927ed7665,369,779b3294-2ca3-4613-a413-bf8d4aa05d16
and it should be at least in the second linked hash- map
String rdsColumns="";
for(String key : mapServer.keySet()){
String[] value = mapServer.get(key);
String[] item = value[0].split(",");
rdsColumns="";
for(String val:item){
rdsColumns = rdsColumns.concat(val + ",");
}
rdsColumns = rdsColumns.concat(" ");
rdsColumns = rdsColumns.replace(", ", "");
info(("Query is: "+ returnSuitableQueryString(rdsColumns, key, alertId, deviceId)));
String query=returnSuitableQueryString(rdsColumns, key, alertId, deviceId);
mapRDS.put(key, insightSQL.returnResultsAsArray(query ,rdsColumns.split(","),rdsColumns));
}
where rdsColumns are the fields I am querying in RDS data-base.
Expected: iterating over both maps and verifying at that all values according to key in the first map contains or equal in the second map.
This is the code you are looking for:
for (String keys : firstMap.keySet()) {
String[] val1 = firstMap.get(keys);
String[] val2 = secondMap.get(keys);
if (Arrays.equals(val1, val2)) {
//return true;
}
ArrayList<Boolean> contains = new ArrayList<>();
for (int i = 0; i < val1.length; i++) {
for (String[] secondMapVal : secondMap.values()) {
List<String> list = Arrays.asList(secondMapVal);
if (list.contains(val1[i])) {
contains.add(true);
break;
} else contains.add(false);
}
}
if (contains.contains(true)) {
//return true; Even a single value matches up
} else {
//return false; Not even a sinle value matches up
}
}
Basically what we have here is a HashMap<String, String>. We take the set of keys and iterate through them. Then we take the value with the key from the two sets. After we got the values we compare them and if they are the same I just print that they match. You can change this and implement this with other types of HashMaps, even where you use custom values. If I didn't understand your problem tell me and I will edit the answer.
So I have an ArrayList that want to make a HashMap of the occurrences of the pairs so B,C = 1 after running through ArrayList1 below. Then B,C after running through ArrayList2 would be B,C = 2
ArrayList1 = {A,B,C,D}
ArrayList2 = {D,B,C,A}
I was planning on using HashMap< String, HashMap< String,Integer >> so that key in parent hashmap would be B and the child key would be C so the pair B,C = 1 after running through ArrayList1. (Sorry if my terminology is wrong just what I'd call each key)
My issue is how would I access current and next element when looping through the ArrayList without getting a ArrayIndexOutOfBoundsException.
If i am getting you right you want to print out the no. of pairs in order like AB - 1, BC - 2, CD - 1, DB - 1, CA - 1. So for such a scenario i would propose a solution like:
lst = {A,B,C,D}
lst2 = {D,B,C,A}
Map<String, Integer> map = new HashMap<String, Integer>();
for ArrayList1
for(int i = 0; i<lst.size()-1; i++)
// checking whether pair already exists
if(map.containsKey(lst.get(i)+lst.get(i+1)))
map.put(lst.get(i)+lst.get(i+1), map.get(lst.get(i)+lst.get(i+1))+1); // if yes increment the current value by one
else
// else add the new key with value 1
map.put(lst.get(i)+lst.get(i+1), 1);
Similarly for ArrayList2
for(int i = 0; i<lst2.size()-1; i++)
// Checking for existing key in same map thus will increment any key matching that of lst keys or any in current lst2
if(map.containsKey(lst2.get(i)+lst2.get(i+1)))
map.put(lst2.get(i)+lst2.get(i+1), map.get(lst2.get(i)+lst2.get(i+1))+1);
else
map.put(lst2.get(i)+lst2.get(i+1), 1);
Thus printing the map
Iterator<Entry<String, Integer>> itr = map.entrySet().iterator();
if(itr.hasNext())
itr.forEachRemaining(new Consumer<Entry<String, Integer>>() {
public void accept(Entry<String, Integer> t) {
System.out.println(t.getKey() +" --> " + t.getValue());
}
});
you can loop Arraylist in this way without any exception
for(String myVar : myArrayList){
//your logic here
}
I have a hash map of places:
HashMap <String, Integer> places = new HashMap <String, Integer>();
places.put("London",0);
places.put("Paris",0);
places.put("dublin",0);
In this places I have a key of places and a value of how many times that place occurs in a text.
Say I have a texts:
iloveLondon
IamforLondon
allaboutParis
Which are also stored in a hashmap:
HashMap <String, Integer> text = new HashMap <String, Integer>();
I have a conditional statement to check if the place is in the text (where capitals and lower case is ignored:
for (String p: places):
{
for(String t : text):
if t.tolowercase().contains(p.tolowercase())
{
//then i would like to increment the value for places of the places hashmap
}
}
In this example, the output should be:
London, 2
Paris, 1
Dublin, 0
Ive got everything, except outputting the values and incrementing it, any suggestions?
To increment a value all you need to do is:
places.put("London",places.get("London")+1);
If the map does not contain "London" then the get will return a null, to handle that case you need to do:
Integer value = places.get("London");
if (value == null) {
value = 1;
} else {
value += 1;
}
places.put("London", value);
I'm going count the most used words in a text and I want to make it this way just need little help how i'm gonna fix the Treemap..
this is how its look like now ...
TreeMap<Integer, List<String>> Word = new TreeMap<Integer, List<String>>();
List<String> TheList = new ArrayList<String>();
//While there is still something to read..
while (scanner.hasNext()) {
String NewWord = scanner.next().toLowerCase();
if (Word.containsKey(NewWord)) {
Word.put(HERE I NEED HELP);
} else {
Word.put(HERE I NEED HELP);
}
}
So what i wanna do is if the NewWord is in the list then add one on Integer(key) and if not Add the word to the next list.
Your type appears to be completely incorrect
... if you want a frequency count
You want to have your word as the key and the count as the value. There is little value in using a sorted collection, but it is many time slower so I would use a HashMap.
Map<String, Integer> frequencyCount = new HashMap<>();
while (scanner.hasNext()) {
String word = scanner.next().toLowerCase();
Integer count = frequencyCount.get(word);
if (count == null)
frequencyCount.put(word, 1);
else
frequencyCount.put(word, 1 + count);
}
... if you want to key by length. I would use a List<Set<String>> This is because your word length is positive and bounded, and you want to ignore duplicate words which is something a Set is designed to do.
List<Set<String>> wordsByLength = new ArrayList<Set<String>>();
while (scanner.hasNext()) {
String word = scanner.next().toLowerCase();
// grow the array list as required.
while(wordsByteLength.size() <= word.length())
wordsByLength.add(new HashSet<String>());
// add the word ignoring duplicates.
wordsByLength.get(words.length()).add(word);
}
All the examples above are correctly storing the count into a map, unfortunately they are not sorting by count which is a requirement you also have.
Do not use a TreeMap, instead use a HashMap to build up the values.
Once you have the complete list of values built you can then drop the entrySet from the HashMap into a new ArrayList and sort that array list by Entry<String,Integer>.getValue().
Or to be neater create a new "Count" object which has both the word and the count in and use that.
Dont do..
TreeMap<Integer, List<String>>
instead do,
TreeMap<String, Integer> // String represents the word... Integer represents the count
because your key (count) can be same sometimes where as the words will be unique...
Do it the other way around... keep reading the words and check if your map contains that word... If yes, increment the count, else add the word with count = 1.
Try this one
TreeMap<String, Integer> Word = new TreeMap<String,Integer>();
while (scanner.hasNext()) {
String NewWord = scanner.next().toLowerCase();
if (Word.containsKey(NewWord)) {
Word.put(NewWord,Word.get(NewWord)+1);
} else {
Word.put(NewWord,1);
}
}
The way to solve this in a time-efficient manner is to have two maps. One map should be from keys to counts, and the other from counts to keys. You can assemble these in different passes. The first should assemble the map from keys to counts:
Map<String, Integer> wordCount = new HashMap<String,Integer>();
while (scanner.hasNext()) {
String word = scanner.next().toLowerCase();
wordCount.put(word, wordCount.containsKey(word) ? wordCount.get(word) + 1 : 1);
}
The second phase inverts the map so that you can read off the top-most keys:
// Biggest values first!
Map<Integer,List<String>> wordsByFreq = new TreeMap<Integer,List<String>>(new Comparator<Integer>(){
public int compare(Integer a, Integer b) {
return a - b;
}
});
for (Map.Entry<String,Integer> e : wordCount) {
List<String> current = wordsByFreq.get(e.getValue());
if (current == null)
wordsByFreq.put(e.getValue(), current = new ArrayList<String>());
current.add(e.getKey());
}
Note that the first stage uses a HashMap because we don't need the order at all; just speedy access. The second stage needs a TreeMap and it needs a non-standard comparator so that the first value read out will be the list of most-frequent words (allowing for two or more words to be most-frequent).
Try this out:
TreeMap<String, Integer> map = new TreeMap<String, Integer>();
Scanner scanner = null;
while (scanner.hasNext()) {
String NewWord = scanner.next().toLowerCase();
if (map.containsKey(NewWord)) {
Integer count = map.get(NewWord);
// Add the element back along with incremented count
map.put(NewWord, count++);
} else {
map.put(NewWord,1); // Add a new entry
}
}