Skip an element from Enumeration Java - java

I want to skip a certain request parameter using Enumeration. I use the below code but it didn't give me the desired result. Can any one tell how would I skip an element from Enumeration or whats wrong with the below code?
for (Enumeration<String> e = request.getParameterNames(); e.hasMoreElements();) {
if("James".equalsIgnoreCase(e.nextElement().toString())) {
e.nextElement();
continue;
} else {
list.add(e.nextElement().toString());
}
}

You are calling nextElement() multiple times per loop skipping multiple elements. You need to only call nextElement() once. Something like...
for (Enumeration<String> e = request.getParameterNames(); e.hasMoreElements();) {
String value = e.nextElement();
if(!"James".equalsIgnoreCase(value)) {
list.add(value);
}
}

Problem is, you are invoking e.nextElement() two times in your if. That will consume two elements.
You should store the element in a String type first, and then do the comparison: -
for (Enumeration<String> e = request.getParameterNames(); e.hasMoreElements();) {
String elem = e.nextElement();
if("James".equalsIgnoreCase(elem)) {
continue;
} else {
list.add(elem);
}
}
And you don't need that toString() after e.nextElement(). It will give you String only, as you are using generic type.
As a side note, I would prefer to use a while loop in this case, as number of iteration is not fixed. Below is the equivalent while loop version for your for-loop: -
{
Enumeration<String> e = request.getParameterNames();
while (e.hasMoreElements()) {
String elem = e.nextElement();
if(!"James".equalsIgnoreCase(elem)) {
list.add(elem);
}
}
}

Related

Java iterate over map twice before deciding whether to remove an object

I have a map of Object string.
I need to iterate over it twice before deciding whether to remove it or not.
protected void removeDayOutOfRangeObjects(Map<Object, String> objects, Calendar[] clientTimeRange) {
String currentPartOfWeek = null;
for(Calendar range: clientTimeRange){
int dayOfWeek = range.get(Calendar.DAY_OF_WEEK);
if(1 == dayOfWeek || 7 == dayOfWeek) {
currentPartOfWeek = "weekends";
} else {
currentPartOfWeek = "weekdays";
}
Iterator<Map.Entry<Object,String>> iter = objects.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<Object,String> entry = iter.next();
if(currentPartOfWeek.matches(entry.getValue())){
continue;
} else {
iter.remove(); // I need to remove the object only if true for both entries in the Calendar array
}
}
}
}
The obvious solution would be to reverse the order of the loops. Have the outer loop iterate over the Map entries, and the inner loop iterate over the array. In the inner loop, set some flag to true the first time your currentPartOfWeek.matches(entry.getValue()) is false (or true, it wasn't clear from your question when you want to remove the entry), and only remove that entry if that flag is true.
This way you only iterate once over the Map.
Basically, it will look like this:
Iterator<Map.Entry<Object,String>> iter = objects.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<Object,String> entry = iter.next();
boolean remove = false;
for(Calendar range: clientTimeRange) {
if (someCondition) {
if (remove) {
iter.remove();
} else {
remove = true;
}
}
}
}
Note that this relies on having two elements in your clientTimeRange array. If there are more elements, you should adjust the logic accordingly (i.e. decide when you want to remove the entry - after two elements of the array match the current Map entry? after all the elements of the array match the current entry?).

Get an element through an iterable string (guava)

I have an Iterable string (guava library). How can I get elements from it. Here is my code:
public static String hillcipher(String str)
{
String hillcipher="";
Iterable<String> pieces = null;
for (int i=0; i<=str.length()-1; i++){
char c = str.charAt(i);
if (Character.isLetter(c)){
pieces = Splitter.fixedLength(2).split(str);
}
}
System.out.println(pieces);
return hillcipher;
here i split a string into pieces of 2 chars each. for example "java" wil be splided to "ja", "va". But then i want to get each character separatly just to do other calculations on them.
There are various ways to get an element from an iterable:
Iterate over each element:
for (String piece : pieces) {
// do something
}
or
Iterator<String> iterator = pieces.iterator();
while (iterator.hasNext()) {
String piece = iterator.next();
// do something
}
etc.
iterating through just the first N elements you want if present:
Iterator<String> iterator = pieces.iterator();
if (iterator.hasNext()) {
String firstPiece = iterator.next();
// do something
if (iterator.hasNext()) {
String secondPiece = iterator.next();
// do something else
// etc.
}
}
using helper functions like those in Guava's Iterables:
String thirdPiece = Iterables.get(pieces, 2);
or
String lastPieceOrEmpty = Iterables.getLast(pieces, "");
etc.
However, if you'd like to simply access the elements like you would a list you can use Splitter.splitToList(CharSequence) instead. It is the same as Splitter.split(CharSequence) but instead of returning a potentially lazy evaluated Iterable it returns a populated ImmutableList which supports random access to its elements.

Java iterator.hasNext() is always true

I have a little problem with the code as seen below. The iterator().hasNext() will never turn into false because the next() function always returns the same element. It ends in an infinite loop.
I would like to set the attribute UserLock in every element in the collection (returned from GetElements()).
If the type of the element is "Package", I will lock all elements under the package with a recursive call of the lockAllElements function.
private void lockAllElements(String internalGUID) {
Element tempElem = null;
while((repo.GetPackageByGuid(internalGUID).GetElements().iterator().hasNext()) == true) {
tempElem = repo.GetPackageByGuid(internalGUID).GetElements().iterator().next();
if(tempElem.GetType().equals("Package")) {
this.lockAllElements(tempElem.GetElementGUID());
}
tempElem.ApplyUserLock();
}
}
It is always true because you get a new Iterator instance in each iteration of your loop. You should get a single Iterator instance and use that instance throughout the loop.
Change
while((repo.GetPackageByGuid(internalGUID).GetElements().iterator().hasNext()) == true) {
tempElem = repo.GetPackageByGuid(internalGUID).GetElements().iterator().next();
...
to
Iterator<Element> iter = repo.GetPackageByGuid(internalGUID).GetElements().iterator();
while(iter.hasNext()) {
tempElem = iter.next();
...
Following on from #Eran's answer... I sometimes prefer a for loop:
for (Iterator<Element> iter = repo.GetPackageByGuid(internalGUID).GetElements().iterator(); iter.hasNext(); ) {
tempElem = iter.next();
}

Java: Get element before or after a given one in an Iterable

Is there a non verbose way (for example using a method call from an existing library, be it guava or similar) to retrieve the previous and the following element from an Iterable, given one of its elements?
I would like to have a general solution that fits for Iterable (or Collection if it is cool enough), so please do not post solutions that work just for Set or List and so on (maybe add a comment :) ).
I need either one or the other, I do not want to find both previous and following element in one method.
My solution is below. If you feel like commenting on returning null instead of throwing IllegalArgumentException or similar, please feel free to do so. The getElementBefore() method creates a new list, which I am not that happy with too.
public static <C> C getElementAfter(final C element, final Iterable<C> iterable) {
Iterator<C> iterator = iterable.iterator();
while (iterator.hasNext()) {
if (iterator.next().equals(element)) {
if (iterator.hasNext()) {
return iterator.next();
} else {
return null;
}
}
}
throw new IllegalArgumentException("Iterable does not contain element.");
}
public static <C> C getElementBefore(final C element, final Iterable<C> iterable) {
return getElementAfter(element, Lists.reverse(Lists.newArrayList(iterable)));
}
Returning null would probably make more sense in this case, as it may not be an exception.
Your getElementBefore implementation could be improved:
public static <C> C getElementBefore(final C element, final Iterable<C> iterable) {
C previous = null;
while (iterator.hasNext()) {
C current = iterator.next();
if (current.equals(element)) {
return previous;
} else {
previous = current;
}
}
return null;
}
I would do something like this:
Iterator<C> iterator = iterable.iterator();
C before = null;
C after = null;
while (iterator.hasNext()) {
C current = iterator.next();
if (current.equals(element)) {
if (iterator.hasNext()) {
after = iterator.next();
}
break;
}
before = current;
}
This should save the element before in before and the element after in after.

Infinite Loop Iterating Through Hashtable

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())

Categories

Resources