I am having hashmap and Arraylist.
Hashmap
Map<Integer, List<String>> mMap = new HashMap<Integer, List<String>>();
Here Key (Interger) will be the index position of one element in the anotherlsit and value will be the list.
Arraylist
List<testBean> mList= new ArrayList<testBean>();
Now I want to iterate the arraylist and compare the indexposition of element in the ArrayList with the key value of Map.If it matched I will go for another logic.I got struck here on how to iterate simultaneously and compare .Please help me on this.
Why not just iterate through the list and use map get:
for(int i = 0;i < mList.size();i++) {
List<String> list = mMap.get(i);
if (list == null) {
// index was a key in map
} else {
// index was not a key in map
}
}
Strictly speaking this is not 100% correct if you have a key in map that maps to a null value. In that case you can check for key presence with mMap.containsKey() method.
for(int i = 0;i < mList.size();i++) {
if(mMap.containsKey(mList.get(i)) {
// Put your logic here
}
}
Theoretically you can do this using iterator:
Iterator<TheBean> itb = mList.iterator();
Iterator<Entry<Integer, List<String>>> itmap = mMap.iterator();
while (itb.hasNext() && itmap.hasNext()) {
TheBean b = itb.next();
Entry<Integer, List<String>> e = itmap.next();
// do you logic that I IMHO do not understand exactly.
}
However this will not work because map does not preserve order of keys. So, if I understand that index of list should match key of map you can do the following:
for (int i = 0; i < mList.size(); i++) {
TheBean b = mList.get(i);
List<String> listOfStrings = mMap.get(i);
if (listOfStrings != null) {
// implement your logic here.
}
}
I hope this helps
Try with this logic
for (Integer mapKey : mMap.keySet()) {
//iterate through list
for (String listIndex : mMap.get(mapKey)) {
//compare the map key value with list value
if(listIndex != null && mapKey == Integer.valueOf(listIndex)){
//write your logic here
}
}
}
Related
I'm pretty new to Java so please be lenient. I have a map, Map<K,V>. I need to iterate through the values, skip the first N indices and add what remains to another list for processing.
For example
Key: foo
Value: [id=001, name=Fred, job=Mailman, age=51],
[id=002, name=Johan, job=Musician, age=335],
[id=003, name=Alice, job=Finance, age=49],
[id=004, name=Marcus, job=Developer, age=41]
I'm sorting by age in descending order and I need to skip over the first N list entries.
The code below is where I'm currently at. Any help is appreciated. Thank you.
List<Object> finalList = new ArrayList<Object>();
List<Object> sortedList = new ArrayList<Object>();
Map<String, List<Object> map = getMapFn();
for(List<Object> anotherList : map.values()) {
Collections.reverse(anotherList);
sortedList = anotherList;
for(Object o : sortedList) {
int skipN = N;
for(int i = 0; i < sortedList.size(); i++) {
if(i < skipN) {
continue;
}
}
finalList.add(o);
}
}
Final Goal:
If N=2,
finalList = [id=003, name=Alice, job=Finance, age=49],
[id=004, name=Marcus, job=Developer, age=41]
in your code,item in sortedList will always add to finalList
int skipN = N;
int index = 0;
for(Object o : sortedList) {
if(index<skipN){
index++;
contine;
}
index++;
finalList.add(o);
}
or use jdk1.8 stream
sortedList.stream().skip(skipN).collect(Collectors.toList())
You don't need the inner loop at all.
int skipN = N;
for(Object o : sortedList) {
if (skipN-- > 0) {
continue;
}
finalList.add(o);
}
Your 2nd and 3rd for loop will perform the same task. I think you do not want this.
So, remove 2nd loop. 3rd loop will be:
get the Nth item from your sortedList using sortedList.get(i)
And, add it into your finalList
for(int i = 0; i < sortedList.size(); i++) {
if(i < skipN) {
continue;
}
finalList.add(sortedList.get(i));
}
Use a sublist of the items to remove and delete all items from it:
for (List<Object> list : map.values()) {
Collections.reverse(list);
list.subList(0, Math.min(list.size(), N)).clear();
}
This creates a sublist that contains the first N items (or the whole list if there are less than N items), then deletes all the items in the sublist via .clear().
Modifications to sublists are reflected in the original list, so the deletions are reflected in the original list.
For interest sake, here's a one-line version:
map.values().stream()
.peek(Collections::reverse)
.map(list -> list.subList(0, Math.min(list.size(), N))
.forEach(List::clear);
but it doesn't look as clear as the multi-line version above.
In my HashMap < String,List< String,String>> I saved keys (Name of a building) and values (Id´s from devices in this building).
I just want to get the size of values from each keys in my HashMap but the only size I get is from the first Key,Value pair...Here´s my code
Map<String, List<String>> moduleNamesWithAllParameters = new
HashMap<String, List<String>>();
List<String> parameters = new ArrayList<String>();
List<String> moduleNames = new ArrayList<String>();
Iterator it;
int start = 0, end = 0, mapKeys = 0;
parameters.add("kExmWoEM2HpMA4CT");
parameters.add("ILm1nApv06lDtqva");
parameters.add("gu00xoO5WPTv0SEr");
parameters.add("kX4FIg6c3C10msex");
parameters.add("xUcA4Y5rvqxlg8ju");
parameters.add("TYjydK6AyY7vwYSo");
parameters.add("#");
parameters.add("IDvHK1vXMiDEPxad");
parameters.add("ja0D3LH8ML0mQwZ0");
parameters.add("#");
parameters.add("tKgYRVvguvl3ByRc");
parameters.add("I95sFdAOoUTHjO7Y");
moduleNames.add("Building 1");
moduleNames.add("Building 2");
moduleNames.add("Building 3");
it = parameters.iterator();
for (int i = 0; i < moduleNames.size(); i++) {
do {
end++;
} while (it.hasNext() && !(it.next().equals("#")));
moduleNamesWithAllParameters.put(moduleNames.get(i), parameters.subList(start, end - 1));
start = end;
}
for (String key : moduleNamesWithAllParameters.keySet())
System.out.println(key + " = " + moduleNamesWithAllParameters.get(key));
Entry<String, List<String>> entry;
for (int i = 0; i < moduleNames.size(); i++) {
entry = moduleNamesWithAllParameters.entrySet().iterator().next();
mapKeys = entry.getValue().size();
System.out.println(mapKeys);
}
}
This line:
entry = moduleNamesWithAllParameters.entrySet().iterator().next();
Is constantly creating a new iterator over the entry set of the map and returning the first entry. So you will only ever see the first entry.
You can change the loop to loop over all entries like this:
for (Entry<String, List<String>> entry : moduleNamesWithAllParameters.entrySet()) {
mapKeys = entry.getValue().size();
System.out.println(mapKeys);
}
Assuming you're using Java8 or later:
moduleNamesWithAllParameters.entrySet().stream().forEach((entry) -> {
System.out.println(entry.getValue().size());
});
Replace your last loop with the following:
for (int i = 0; i < moduleNames.size(); i++) {
mapKeys = moduleNamesWithAllParameters.get(moduleNames.get(i)).size();
System.out.println(mapKeys);
}
Or a bit neater:
for(String key : moduleNamesWithAllParameters.keySet()) {
System.out.println(moduleNamesWithAllParameters.get(key).size());
}
Or even neater (Java 8+):
moduleNamesWithAllParameters.stream().forEach(entry ->
System.out.println(entry.getValue().getSize())
);
Or loop using valueSet (since you don't actually use the key):
for(List<String> value : moduleNamesWithAllParameters.valueSet()) {
System.out.println(value.size());
}
Or if you so fancy (Java 8+):
moduleNamesWithAllParameters.valueSet().stream().map(List::size).forEach(System.out::println);
Probleam is happend in this line:
entry = moduleNamesWithAllParameters.entrySet().iterator().next();
entrySet().iterator() is a new object each time it loops.
So you map size only is the first size.
I have a Map with key as String and value as List as below
<Key>Path1 Value=[164,123,111,131]
<Key>Path2 Value=[164,122,135,133]
<Key>Path3 Value=[190,144,100,126]
<Key>Path4 Value=[113,122,453,117]
I want to compare each Key's Value with other Key's Value like Path1 Value with rest of Path's values and so on,
and also no duplicate comparision should happen, like if Path1 value is compared in 1st iteration . It should not compare Path2 with Path1 in 2nd iteration.
Am stuck with this problem . Please help me with any solution. Thanks in advance .
I have started with following code :
for (Map.Entry<String, List<String>> entry : map1.entrySet()) {
String key = entry.getKey();
for (String val : entry.getValue()) {
// do something with key and each val
}
}
Only compare keys where the first is less than the second, or some similar simple strategy.
for (String key1 : map.keySet()) {
for (String key2 : map.keySet()) {
if (key1.compareTo(key2) < 0) {
// compare key1 to key2
}
}
}
Maybe, this would be a better strategy than one suggested by Peter Lawrey cause it's not O(N*N)
Map<String, List<String>> map = new HashMap<>();
map.put("Path1", new ArrayList<>(Arrays.asList("164","123","111","131")));
map.put("Path2", new ArrayList<>(Arrays.asList("164","122","135","133")));
map.put("Path3", new ArrayList<>(Arrays.asList("190","144","100","126")));
map.put("Path4", new ArrayList<>(Arrays.asList("113","122","453","117")));
List<String> list = new LinkedList<>(map.keySet());
for (int i = 0; i < list.size(); i++) {
for (int j = i + 1; j < list.size(); j++) {
List<String> temp = new ArrayList<>(map.get(list.get(i)));
if (temp.removeAll(map.get(list.get(j)))) {
// do what you want
System.out.println(list.get(i) + " has duplicates with " + list.get(j));
}
}
}
I am trying to find the number of Strings that only appear exactly once in an ArrayList.
How many I achieve this (preferably with the best possible time complexity)?
Below is my method:
public static int countNonRepeats(WordStream words) {
ArrayList<String> list = new ArrayList<String>();
for (String i : words) {
list.add(i);
}
Collections.sort(list);
for (int i = 1; i < list.size(); i++) {
if (list.get(i).equals(list.get(i - 1))) {
list.remove(list.get(i));
list.remove(list.get(i - 1));
}
}
System.out.println(list);
return list.size();
}
Why doesn't it remove the String at list.get(i) and list.get(i-1)?
There is no need for sorting.
A better approach would be to use two HashSet One for maintaining repeating and one for non-repeating words. Since HashSet internally uses HashMap, Ideally contains, get, put operation has o(1) complexity. So the overall complexity of this approach would be o(n).
public static int countNonRepeats(List<String> words) {
Set<String> nonRepeating = new HashSet<String>();
Set<String> repeating = new HashSet<String>();
for (String i : words) {
if(!repeating.contains(i)) {
if(nonRepeating.contains(i)){
repeating.add(i);
nonRepeating.remove(i);
}else {
nonRepeating.add(i);
}
}
}
System.out.println(nonRepeating.size());
return nonRepeating.size();
}
Here's one simple suggestion:
First, sort your array by alphanumerical order
Iterate through with a loop, if( !list.get(i).equals(list.get(i+1)) ) → unique
If you find duplicates, increment i until you reach a different string
This will have the complexity of the sorting algorithm, since step 2+3 should be O(n)
Is there any specific need of using an ArrayList? You can do it easily by using a HashSet.
Here is the code snippet:
public static void main (String[] args) {
String[] words = {"foo","bar","foo","fo","of","bar","of","ba","of","ab"};
Set<String> set = new HashSet<>();
Set<String> common = new HashSet<>();
for (String i : words) {
if(!set.add(i)) {
common.add(i);
}
}
System.out.println(set.size() - common.size());
}
Output:
3
Here is the modified code:
public static int countNonRepeats(WordStream words) {
Set<String> set = new HashSet<>();
Set<String> common = new HashSet<>();
for (String i : words) {
if(!set.add(i)) {
common.add(i);
}
}
return (set.size() - common.size());
}
You can use hashmap to achieve this.With this approach we can count the occurrence of all the words, If we are interested in only unique words then access the element having count = 1.
HashMap<String,Integer> - key represents the String from arraylist and Integer represents the count of occurrence.
ArrayList<String> list = new ArrayList<String>();
HashMap<String, Integer> hashMap = new HashMap<String, Integer>();
for (int i = 0; i < list.size(); i++) {
String key = list.get(i);
if (hashMap.get(key) != null) {
int value = hashMap.get(key);
value++;
hashMap.put(key, value);
} else {
hashMap.put(key, 1);
}
}
int uniqueCount = 0;
Iterator it = hashMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next();
if ((int) pair.getValue() == 1)
uniqueCount++;
}
System.out.println(uniqueCount);
If I have an ArrayList of these strings...
"String1, String1, String1, String2, String2, String2, String3, String3"
How can I find the most appearing string in this list? If there are any duplicates, I would want to put both into the same list and deal with that accordingly. How could I do this, assuming that the list of strings could be of any size.
This is about as far as I've gotten:
public String getVotedMap() {
int[] votedMaps = new int[getAvailibleMaps().size()];
ArrayList<String> mostVoted = new ArrayList<String>();
int best = 0;
for(int i = 0; i < votedMaps.length; i++) {
if(best > i) {
best = i;
} else if(best == i) {
} else {
}
}
}
getAvailibleMaps() is a list of Maps that I would choose from (again, can get any size)
Thanks!
Use HashMap
The basic Idea is loading all the values into a hashtable. Hash tables are nice because you can assign a value to a unique key. As we add all the keys to the hashtable we are checking to see if it already exists. If it does then we increment the value inside.
After we have inserted all the elements into the hashtable then we go through the hashtable one by one and find the string with the largest value. This whole process is O(n)
Map<String, Integer> map = new HashMap<String, Integer>();
for(int i = 0; i < array.length(); i++){
if(map.get(array[i]) == null){
map.put(array[i],1);
}else{
map.put(array[i], map.get(array[i]) + 1);
}
}
int largest = 0;
String stringOfLargest;
for (Map.Entry<String, Object> entry : map.entrySet()) {
String key = entry.getKey();
int value = entry.getValue();
if( value > largest){
largest = value;
stringOfLargest = key;
}
}
if you want multiple largest strings then instead of just finding the largest and being done. You can add all the largest to a mutable list.
for example:
int largest = 0;
for (Map.Entry<String, Object> entry : map.entrySet()) {
String key = entry.getKey();
int value = entry.getValue();
if( value > largest){
largest = value;
}
}
ArrayList<Object> arr = new ArrayList<Object>();
for (Map.Entry<String, Object> entry : map.entrySet()) {
String key = entry.getKey();
int value = entry.getValue();
if( value == largest){
arr.add(key);
}
}
arr now stores all the most frequently appearing strings.
This process is still O(n)
Just iterate through the list and keep a HashMap<String,Integer> that counts how many times the string has appeared, eg.
Map<String,Integer> counts = new HashMap<String,Integer>();
for(String s : mostVoted) {
if(counts.containsKey(s)) {
counts.put(s,counts.get(s)+1);
} else {
counts.put(s,1);
}
}
// get the biggest element from the list
Map.Entry<String,Integer> e = Collections.max(counts.entrySet(),new Comparator<Map.Entry<String,Integer>>() {
#Override
public int compare(Map.Entry<String,Integer> o1, Map.Entry<String,Integer> o2) {
return o1.getValue().compareTo(o2.getValue());
}
});
System.out.printf("%s appeared most frequently, %d times%n",e.getKey(),e.getValue());
If you can use java 8, this will give you a list of most frequent strings or throw an exception if the list is empty.
List<String> winners = strings.stream()
.collect(groupingBy(x->x, counting())) // make a map of string to count
.entrySet().stream()
.collect(groupingBy( // make it into a sorted map
Map.Entry::getValue, // of count to list of strings
TreeMap::new,
mapping(Map.Entry::getKey, toList()))
).lastEntry().getValue();