Performing Loop Unrolling while iterating the hashmap - java

I am looking at a possibility of unrolling the loop which is written to iterate the elements in a hash map.Below posted is the code.
for (final Object key : map.keySet())
{
if (input_map.containsKey(key))
{
System.out.println("Matching key: " + key);
if (map.get(key).equals(input_map.get(key)))
{
System.out.println("hii!done");
}
else
{
System.out.println(key);
final String values =
key.
toString().
substring(key.toString().lastIndexOf("\\") + 1);
System.out.println("input_map" +
input_map.get(key));
System.out.println("map" + map.get(key));
}
}
}
Explanation:
Currently, comparison in the loop is being done based on one element at a time i.e "key".I am looking at a possibility where i can retrieve the next successive keys in one single iteration i.e(key,key+1,key+2).
Any Suggestions would be highly helpful.

Use the KeySet or EntrySet iterator() method and while loop through with hasNext() and next(). You need to handle cases where it has not 3 repeating elements. Then you have the 3 keys and should be able to easily access the values in the Map.
Iterator<Integer> it = myMap.keySet().iterator();
while(it.hasNext())
{
int first = it.next();
int second = it.next();
int third = it.next();
}

Related

Adding elements to an HashMap concurrently

If I iterate over a standard HashMap and attempt to add elements to it while iterating I get ConcurrentModificationException.
So I try an HashMap allowing concurrent adds:
ConcurrentHashMap<String, Integer> cMap = new ConcurrentHashMap<>();
cMap.put("one", 1);
cMap.forEach((key, value) -> cMap.put(key + key, value + value));
System.out.println(cMap);
However, the resulting map is a bit weird:
{oneoneoneoneoneoneoneone=8, one=1, oneone=2, oneoneoneone=4}
and if changing the key to zx (cMap.put("zx", 1)), the result is now:
{zxzx=2, zx=1}
Questions:
1) Why this happens? The two concurrent operations (iterating and adding) should not conflict.
2) How to fix the inconsistency?
As opposite to Collections, when changing a String while iterating over the chars of that String, this issue is not being met:
String str = scanner.next();
for (int i = 1; i < str.length(); i++) {
if (str.charAt(i) == str.charAt(i-1)) {
str = str.substring(0, i-1) + str.substring(i+1);
i = 0;
}
}
if (str.length() == 0) {
System.out.println("Empty String");
} else {
System.out.println (str);
}
}
note that in the above loop, the source String isn't actually changed but re-assigned because String is immutable and can not be modified.
The above code works fine and consistently. Is this an example of why Strings are thread safe?
It comes down to which hash bucket your new elements get added. In your first example, your new elements get added to a later hash bucket than the one you're working on, and which the iterator has yet to reach. In your second example, your new elements get added to an earlier hash bucket, which the iterator has already read.
You should be very wary about modifying collections in the middle of an iteration. In your case, it might be better for you to add your new entries into a new map, and then merge them together.

How can I remove Strings from an ArrayList which contain only whitespace characters?

I want to remove all strings in a list which contain only whitespace characters. I tried the following code, but some lines were not removed:
List<String> getarray = /* ... */;
for (int i = 0; i < getarray.size(); i++) {
if (getarray.contains(" ").getarray.contains(null)) {
getarray.remove(i);
} else {
System.out.println("a: " + getarray.get(i));
}
}
This does only work for certain inputs, can somebody help me understand why?
Here is a list of inputs which did not work as intended
First of all use some Iterator to iterate and perform your operation of removing elements from ArrayList.
Second to solve your problem of empty string , you could use trim() and isEmpty() methods
try below code:
Iterator<String> it = getarray.iterator();
while (it.hasNext()) {
String myValue = it.next();
if (myValue.trim().isEmpty()) {
it.remove();
} else {
System.out.println("a: " + myValue);
}
}
Use Iterators if you want to remove elements. According to Java docs:
Iterator takes the place of Enumeration in the Java Collections Framework. Iterators differ from enumerations in two ways:
Iterators allow the caller to remove elements from the underlying collection during the iteration with well-defined semantics.
Method names have been improved
Try the following code:
Iterator<String> itr = getarray.iterator();
while (itr.hasNext()) {
String value = itr.next();
if (value.trim().isEmpty()) {
itr.remove();
} else {
System.out.println("a: " + value);
}
}
You misunderstand between element is empty or only composed of spaces AND element contain spaces :
So it's element.trim().isEmpty() instead of element.contains(" ");
.trim() removes spaces at start and at the ens of the String
So this will do your stuff, it will iterate over the list, and only keep the element which are not empty (or only compsed of spaces)
getarray = getarray.stream().filter(s -> !s.trim().isEmpty()).collect(Collectors.toList());
If you wan to print all after just do : getarray.forEach(System.out::println);

Optimisation of searching HashMap with list of values

I have a map in which values have references to lists of objects.
//key1.getElements() - produces the following
[Element N330955311 ({}), Element N330955300 ({}), Element N3638066598 ({})]
I would like to search the list of every key and find the occurrence of a given element (>= 2).
Currently my approach to this is every slow, I have a lot of data and I know execution time is relative but it takes 40seconds~.
My approach..
public String occurance>=2 (String id)
//Search for id
//Outer loop through Map
//get first map value and return elements
//inner loop iterating through key.getElements()
//if match with id..then iterate count
//return Strings with count == 2 else return null
The reason why this is so slow is because I have a lot of ids which I'm searching for - 8000~ and I have 3000~ keys in my map. So its > 8000*3000*8000 (given that every id/element exists in the key/valueSet map at least once)
Please help me with a more efficient way to make this search. I'm not too deep into practicing Java, so perhaps there's something obvious I'm missing.
Edited in real code after request:
public void findAdjacents() {
for (int i = 0; i < nodeList.size(); i++) {
count = 0;
inter = null;
container = findIntersections(nodeList.get(i));
if (container != null) {
intersections.add(container);
}
}
}
public String findIntersections(String id) {
Set<Map.Entry<String, Element>> entrySet = wayList.entrySet();
for (Map.Entry entry : entrySet) {
w1 = (Way) wayList.get(entry.getKey());
for (Node n : w1.getNodes()) {
container2 = String.valueOf(n);
if (container2.contains(id)) {
count++;
}
if (count == 2) {
inter = id;
count = 0;
}
}
}
if (inter != (null))
return inter;
else
return null;
}
Based on the pseudocode provided by you, there is no need to iterate all the keys in the Map. You can directly do a get(id) on the map. If the Map has it, you will get the list of elements on which you can iterate and get the element if its count is > 2. If the id is not there then null will be returned. So in that case you can optimize your code a bit.
Thanks

How to obtain first 5 values from a LinkedHashSet?

I have a LinkedHashSet which contains multiple number of values.
LinkedHashSet<String> lhs = new LinkedHashSet<String>();
I want to iterate through the set of values and display the first five values from the number of items stored in the set. I have used a for loop to iterate through values and display data, see below:
for (String sent : lhs) {
text.append(sent);
}
This outputs all the values stored in the LinkedHashSet. What alterations should I make to my code in order to only get the first 5 values from the set.
You can get your sets Iterator
Iterator<String> it = yourSet.iterator();
and move to next() element N times (assuming that it still hasNext() element)
int counter = 0;
while(it.hasNext() && counter++ < N){
String element = it.next();
...
}
int i = 0;
for (String sentences : lhs) {
if (i > 4) break;
text.append(sentences);
i++;
}
If you had java8, then I would suggest something like this:
yourLinkedHashSet
.stream()
.limit(5)
.forEachOrdered(text::append);
Explanation:
stream() will take one String after another from the collection
limit(5) will stop the calculations after five elements are processed
forEachOrdered(...) takes an action for each item, one after another
text::append is the action to be done per item
You can use subList without counter declaration
Iterator<String> iter = new ArrayList<>(lhs).subList(5, lhs.size())
.iterator();
while (iter.hasNext()) {
text.append(iter.next());
}

Retrieving specific values in Multimap

I'm using a Multimap that has two values per key. Below is the code I'm using to get each value separately:
The first bit of code gets the first object value:
for(Object object : map.get(object))
{
return object
}
Then, I'm using another method to retrieve the other value. This method takes the first object as an argument:
for(Object object : team.get(object))
{
if(object != initialObject)
{
return object;
}
}
This seems like a 'hackish' way of doing things, so is there any way for me to get the values more easily?
If you're using Guava, Iterables#get is probably what you want - it returns the Nth item from any iterable, example:
Multimap<String, String> myMultimap = ArrayListMultimap.create();
// and to return value from position:
return Iterables.get(myMultimap.get(key), position);
If you're using a ListMultimap then it behaves very much like a map to a List so you can directly call get(n).
Collection<Object> values = map.get(key);
checkState(values.size() == 2, String.format("Found %d values for key %s", values.size(), key));
return values.iterator().next(); // to get the first
Iterator<Object> it = values.iterator();
it.next(); // move the pointer to the second object
return it.next(); // get the second object
for getting all the values for the same key the most easiest way to do it will be :
Iterator iterator = multimap.get(key).iterator();
System.out.println("first element: " + iterator.next());
System.out.println("second element: " + iterator.next());
System.out.println("third element: " + iterator.next());
And so on
another option if you want to get all the elements without know how much elements there
Iterator iterator = multimap.get(key).iterator();
int index=1;
while (iterator.hasNext()) {
System.out.println(index +" element: " + iterator.next());
index++;
}

Categories