Im trying to get an object out of a HashMap and call a method from this object.
But insted of getting the object, I get a normal java.lang.Object.
public void setExits(HashMap<Direction, Exit> e){
this.exits = e;
Iterator it = e.entrySet().iterator();
while (it.hasNext()) {
Map.Entry exits = (Map.Entry) it.next();
Exit r = exits.getValue(); //HERE I GET ERROR
}
}
You are declaring type constraints in the method signature but in the method body you are not taking any advantage of using the type constraints.
What you are doing is similar to you are using HashMap< Object, Object >. That is why compile error.
Correct Code:
public void setExits(HashMap<Direction, Exit> e){
this.exits = e;
Iterator<Map.Entry<Direction, Exit>> it = e.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Direction, Exit> entry = it.next();
Exit r = entry.getValue(); // OK
}
}
Change this line:
Iterator it = e.entrySet().iterator();
to:
Iterator<Entry<Direction, Exit>> it = e.entrySet().iterator();
Here is how I might iterate every value in a HashMap
HashMap<Directive, Exit> tempHashMap = new HashMap<>();
for(Directive directive:tempHashMap.keySet()){
Exit tempExit = tempHashMap.get(directive);
//do what you want with the exit
}
You are using a HashMap like a list. It's not a very effective list.
Instead do
Object value = map.get(key);
And it will skip the items that aren't under the key, very efficiently.
public void setExits(HashMap<Direction, Exit> exits, Direction direction){
this.exits = e.get(direction);
}
What you have missed is the generics for the Map.Entry.
It looks to me as though you are trying to loop over all the entries of the map, you might find a for loop easier.
for(Map.Entry<Direction, Exit> entry : e.entrySet()) {
Direction dir = entry.value();
//do stuff
}
Related
I want to remove all entries from a LinkedHashMap that were added after an entry with a given key.
My first try was:
LinkedHashMap<String, SomeObject> var = new LinkedHashMap<String, SomeObject>();
public void removeEntriesAfter(String key) {
boolean deleteEntries = false;
for (String currentKey : var.keySet()) {
if(deleteEntries) {
var.remove(currentKey);
} else {
if(key.equalsIgnoreCase(currentKey)) {
// Do not remove the current entry
deleteEntries = true;
}
}
}
}
But then I received a java.util.ConcurrentModificationException.
My second idea was to first determine the keys, an remove them afterwards.
public void removeEntriesAfter(String key) {
boolean deleteEntries = false;
List<String> listOfEntriesToBeRemoved = new ArrayList<String>();
// Determine entries to be deleted
for (String currentKey : var.keySet()) {
if(deleteEntries) {
listOfEntriesToBeRemoved.add(currentKey);
} else {
if(key.equalsIgnoreCase(currentKey)) {
// Do not remove the current entry
deleteEntries = true;
}
}
}
// Removed selected entries
for (String currentKey : listOfEntriesToBeRemoved) {
var.remove(currentKey);
}
}
That works, but I'm sure there is a more elegant/efficient way of doing this.
To avoid a ConcurrentModificationException you can use an Iterator.
Iterator<String> it = map.keySet().iterator();
while (it.hasNext())
if (it.next().equalsIgnoreCase(currentKey))
break;
while (it.hasNext()) {
it.next();
it.remove();
}
If you wanted the most efficient solution, it would be to go straight to the appropriate entry in the first place. To do this you would have to only ever put lower case keys into the map (rather than putting any old strings and comparing using equalsIgnoreCase). Then, using reflection, you could access the Map.Entry object corresponding to currentKey.toLowerCase() and then, using reflection again, you could follow the links all the way through the map. None of this is possible without reflection because neither the entry corresponding to a key nor the links between entries are exposed through public API. I do not recommend reflection as your code could easily break in the future if the code for LinkedHashMap is changed.
I am trying to iterate custom object using iterator and adding data into that custom object but when size of object is 1 it's working but when I am adding second data it gives me an error : nested exception is java.util.ConcurrentModificationException
My Code is as Follow :
public List<ValidationObject> _validationObjects = new ArrayList<>();
public void addError(String key, String value){
int size = _validationObjects.size();
if(size==0){
ValidationObject vo = new ValidationObject();
vo.setKey(key);
vo.addLine(value);
_validationObjects.add(vo);
}
else{
Iterator i = _validationObjects.iterator();
while(i.hasNext()){
ValidationObject obj = (ValidationObject)i.next();
if(obj.getKey().equals(key)){
obj.addLine(value);
}else{
ValidationObject vo = new ValidationObject();
vo.setKey(key);
vo.addLine(value);
_validationObjects.add(vo);
}
}
}
}
In class ValidatioObject I have variable as follow :
private List<String> _lines;
private String _key;
I am calling addError() method as follow :
list.addError("Name", "Should not empty");
list.addError("Prefix", "Should not empty");
Any Help on it, why it's behaving like this.
I think you need to change the logic. Add to your list outside the iterator
else{
boolean keyFound = false;
Iterator i = _validationObjects.iterator();
while(i.hasNext()){
ValidationObject obj = (ValidationObject)i.next();
if(obj.getKey().equals(key)){
obj.addLine(value);
keyFound = true;
}
}
if(!keyFound){
ValidationObject vo = new ValidationObject();
vo.setKey(key);
vo.addLine(value);
_validationObjects.add(vo);
}
}
Why this exception is because of this line,
_validationObjects.add(vo);
beacuse,
If the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException.
So try adding that using the iterator instance only.
Define a ListIterator and add to that,
ListIterator i=_validationObjects.listIterator();
i.add(vo);
I'm trying find the most popular word in an array using Hashtables. For some reason the while loop is looping infinitely. I've debugged and the element never changes from the first one it gets. Any ideas on why this is happening?
Here is my code:
import java.util.Hashtable;
public class MyClass {
public String mostPopularString (String []words) {
if (words == null)
return null;
if (words.length == 0)
return null;
Hashtable<String, Integer> wordsHash = new Hashtable<String, Integer>();
for (String thisWord : words)
{
if (wordsHash.containsKey(thisWord))
{
wordsHash.put(thisWord, wordsHash.get(thisWord) + 1);
}
else
{
wordsHash.put(thisWord, 1);
}
}
Integer mostPopularCount = 0;
String mostPopularWord = null;
boolean tie = false;
while (wordsHash.keys().hasMoreElements())
{
String currentWord = (String) wordsHash.keys().nextElement();
if (wordsHash.get(currentWord) > mostPopularCount)
{
mostPopularCount = wordsHash.get(currentWord);
mostPopularWord = currentWord;
tie = false;
}
else if (wordsHash.get(currentWord) == mostPopularCount)
{
tie = true;
}
}
if (tie)
return null;
else
return mostPopularWord;
}
}
You're calling wordsHash.keys() on each iteration of the loop, which gives you a fresh Enumeration<String> on each iteration - you're then calling it again inside the loop.
You want to call it once, and then iterate over the single Enumeration<String>:
Enumeration<String> iterator = wordsHash.keys();
while (iterator.hasMoreElements())
{
String currentWord = iterator.nextElement();
...
}
Note that as you're also getting the value for each element, you'd be better off iterating over the entrySet() rather than the keys().
You'd also be better off using HashMap instead of Hashtable, as then you could just use an enhanced for loop...
The problem is in line
while (wordsHash.keys().hasMoreElements())
each time through the loop, you are getting a new copy of the enumeration. You'll want to get the keyset once, and iterate over that.
It would probably be easier to use an enhanced for Loop here as well
for (Map.Entry<String,Integer> entry : wordsHash.entrySet()) {
String currentWord = entry.getKey();
Integer currentCount = entry.getValue();
//more code here
}
This should provide the behavior you want, while being simpler and easier to read.
The problem is that whenever you call wordsHash.keys(), it returns a new enumeration:
while (wordsHash.keys().hasMoreElements()) // <=== HERE
{
String currentWord = (String) wordsHash.keys().nextElement(); // <=== AND HERE
What you need to do is create a single enumeration and use it throughout the loop.
P.S. Why are you using Hashtable and not HashMap?
Every call to .keys() returns a new enumeration, with a new internal pointer for iterating:
Hashtable table = new Hashtable();
table.put("a", "a");
table.put("b", "b");
boolean b = table.keys() == table.keys();
System.out.println(b); // false
// the two calls to `.keys()` returned different instances of Enumeration
So assign your keys enumeration to a variable:
Enumeration keys = wordsHash.keys();
while (keys.hasMoreElements())
{
String currentWord = (String) keys.nextElement();
}
Change your code to:
Enumeration<String> keys = wordsHash.keys();
while (keys.hasMoreElements()) {
String currentWord = keys.nextElement();
So that a new enumeration pointing to the first key of the HashTable is not created every time that you enter the loop.
Nothing is modifying the wordsHash. That means that if wordsHash.keys().hasMoreElements() is true once, it'll continue to be true for the rest of the program. This causes an infinite loop. You either need to remove the keys as you go along or you should just use a for
you get a new Iterable ofer all keys each loop iteration: wordsHash.keys() as long as there is at least one key in it the while loop never ends.
Replace:
while (wordsHash.keys().hasMoreElements()){
String currentWord = (String) wordsHash.keys().nextElement();
by
for (String currentWord: wordsHash.keys()){
Also, unrelated to your Enumeration issue, this is probably a defect:
else if (wordsHash.get(currentWord) == mostPopularCount)
That's a reference comparison of a java.lang.Integer to another java.lang.Integer. It is not a comparison of the actual values they represent. It is working for "small" numbers because auto-boxing uses cached references, but will eventually break. You probably want:
else if (wordsHash.get(currentWord) == mostPopularCount.intValue())
I know that there are lots of threads on NoSuchElementException in Java here but I still cannot figure out what is going on here
I am trying to come up with a solution for Transitive Dependencies Kata 18 which is posted at http://codekata.pragprog.com/2007/01/kata_eighteen_t.html
dependencies_for method is supposed to take in a char item and compute all dependencies for the item. The exception occurs when I try to add an element to finalDependencies ArrayList
This is the place where my NullPointerException occurs. I have traced all of these data structures and none of them have a Null value. I don't understand what is causing my exception here. Please see my code:
public class Test_Dependencies
{
public static void main(String[] args) {
Dependencies Dep = new Dependencies();
Dep.add_direct('A', "B C");
Dep.add_direct('B', "C D");
Dep.dependencies_for('A');
}
}
public class Dependencies {
HashMap dependenciesList;
public Dependencies()
{
HashMap<Character, ArrayList> dependenciesList = new HashMap<Character, ArrayList>();
}
public void add_direct(char mainItem, String dependentItems)
{
// code that works here
}
public String dependencies_for(char item)
{
ArrayList finalDependencies = new ArrayList<Character>();
Character key = new Character(item);
//get initial dependencies for the item and add them
ArrayList processingDependencies = dependenciesList.get(key);
Iterator itr = processingDependencies.iterator();
while(itr.hasNext())
{
if(finalDependencies.contains(itr.next()) == false && itr.next() != key)
{
// NoSuchElement exception here
finalDependencies.add(itr.next());
// look again at each item in dependenciesList. If it is in the list then add it to processingDependencies
if(dependenciesList.containsKey(itr.next()) && !processingDependencies.contains(itr.next()))
{
processingDependencies.add(itr.next());
}
}
}
// turn finalDependencies into a string
itr = finalDependencies.iterator();
String allDependencies = "";
while(itr.hasNext())
{
allDependencies = allDependencies + " " + itr.next();
}
return allDependencies;
}
}
I am a bit perprlexed because processingDependencies and finalDependencies ArrayLists are not null. And processingDependencies arraylist contains an item
You are calling twice. The first call is "protected" by a matching hasNext Call. The second is not. Save the result of next into a temporary variable and use that, instead of using the value directly, since every call to next will try to advance the iterator first. In the good case, you get an exception. In the bad case, things seem to work, but your program is dealing with the wrong value.
You can't do this:
while(itr.hasNext())
{
if(finalDependencies.contains(itr.next()) == false && itr.next() != key)
{
// NoSuchElement exception here
finalDependencies.add(itr.next());
// stuff removed
}
}
You must verify that iter.hasNext() is true prior to each call of itr.next(). What happens when you reach the last item in itr, but then call itr.next() three times?
Answer: NoSuchElementException. Check out Iterator
The problem is here:
HashMap dependenciesList;
public Dependencies()
{
HashMap<Character, ArrayList> dependenciesList = new HashMap<Character, ArrayList>();
}
You declare a hashmap called dependenciesList. You then try to instantiate that list, but what you actually do is create a local variable named the same thing. They are two separate variables. Then you try to use the one that hasn't been instantiated here:
ArrayList processingDependencies = dependenciesList.get(key);
What you need to do is instantiate the first dependenciesList instead of creating a new one
(I'm not a pro at java, but something like dependenciesList = new HashMap....() instead of HashMap<..> dependenciesList = new HashMap...() )
I was just wondering what the easiest way to iterate over a set indefinitely, i.e. when it reaches the end it next(); calls the first object. I'm assuming that this is not an already predefined function in Java, so just looking for the easiest way to implement this in Java.
There's a method in the excellent Google Collections library which does this:
Set<String> names = ...;
Iterable<String> infinite = Iterables.cycle(names);
(I can't recommend the Google Collections library strongly enough. It rocks very hard. I'm biased as I work for Google, but I think pretty much every Googler writing Java would tell you how useful the collections are.)
Iterator it = mylist.iterator();
while (it.hasNext())
{
MyType t = (MyType)it.next();
// do something
if (!it.hasNext())
it = mylist.iterator();
}
Try EndlessIterator from Cactoos:
Iterator<String> names = new EndlessIterator<>("John");
It will always return "John" and will never end.
Also, check EndlessIterable, which implements Iterable and does the same.
If you're making the iterator, in the next method you can have an if condition that checks if there's another object in the list. If there is, then you return that object, if there isn't then you go back to the start of the list and return that object.
This is what I can think of...
iterator = set.getIterator
//other code
if (iterator.hasNext())
//do code here
else
iterator = set.getIterator();
How about ?
List<String> list = // ArraysList
Interator<String> it = null;
while(true) {
it = list.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
If you don't want to use Guava but still want a reusable solution:
public static class CyclicIterator<E, C extends Collection<E>> implements Iterator<E> {
final private C mElements;
private Iterator<E> mIterator;
public CyclicIterator(C elements) {
mElements = elements;
mIterator = elements.iterator();
}
#Override
public boolean hasNext() {
if (! mIterator.hasNext()) {
mIterator = mElements.iterator();
}
return mIterator.hasNext();
}
#Override
public E next() {
if (! mIterator.hasNext()) {
mIterator = mElements.iterator();
}
return mIterator.next();
}
}
Note: this doesn't support the remove() method but it could easily be added if needed. Also it's not thread safe.
I think what you want never help You can do anything with your iterator that's easy but you must be carefull with any new thing you add im not used with this style but this is what you want though :
if (! It.hasNext() )
{
while ( It.hasPrevious() )
{
It = It.Previous();
}
} else {
It = It.Next();
}
This way is nothing if your really interested you should instead make next pointer of the last to the first always when pushing a new list.
std jdk:
Iterable<String> infinite = Stream.generate(names.stream()).flatMap(e -> e).iterator()