I have a static method where I get a list of tweets and the name of a town as a parameter and I remove from the list whichever tweet did not originate from the town or the user that made it did not originate from the town.
Here is my code:
public static void removeIncorrectTowns(List<Status> tweets, final String town) {
if (town.isEmpty()) {
return;
}
Iterator<Status> it = tweets.iterator();
while (it.hasNext()) {
Status status = it.next();
if ((status.getPlace() == null && (status.getUser().getLocation() == null || !status.getUser().getLocation().equalsIgnoreCase(town)))
|| !status.getPlace().getName().equalsIgnoreCase(town)) {
it.remove();
}
}
}
The problem I have is that I got a NullPointerException at line 62 which is the line with it.remove().
How is it even possible for the iterator to be null? That alone makes no sense to me since the while loop checks if it.hasNext().
In the case that status.getPlace() is null and status.getUser().getLocation() is not null and does not equal town, you are going to get a NPE in the last part of the condition when status.getPlace().getName() is called.
Related
My method applyBonus() from the class BonusEmporium gets bonus objects from the arrayList of City objects and applies them to a Player object.
when i write my function like this i have no problem testing it:
public class BonusEmporium extends Bonus {
public BonusEmporium(int cities) {
this.setBonusType(BonusType.EMPORIUM);
this.cities=cities;
setCity(new ArrayList<City>(cities));
}
public void applyBonus(Player player){
Bonus bonus=getCity().get(0).getBonus().get(0);//gets the first bonus from the first
//city
bonus.applyBonus(player);
Bonus bonus=getCity().get(0).getBonus().get(1);//gets the second bonus from the first
//city
bonus.applyBonus(player);
Bonus bonus=getCity().get(1).getBonus().get(0);//gets the first bonus from the
//second city
bonus.applyBonus(player);
}
}
The problem is when i want to run it only while the arraylists contain elements, how do i check that an element from an array is empty?
public class BonusEmporium extends Bonus {
public BonusEmporium(int cities) {
this.setBonusType(BonusType.EMPORIUM);
this.cities=cities;
setCity(new ArrayList<City>(cities));
}
public void applyBonus(Player player){
int i=0,j=0;
while(j<cities){
while(getCity().get(j).getBonus().get(i)!=null){//In theory this should
//verify that the element bonus i from the city j is not empty
//but i get NullPointerException
Bonus bonus=getCity().get(j).getBonus().get(i);
bonus.applyBonus(player);
i++;
}
j++;
}
}
}
It's difficult to tell what you are asking, but you should be able to avoid the error by handling the message chain better.
public void applyBonus(Player player){
List<City> cities = getCity();
for(int i = 0; cities != null && i < cities.size(); i++){
City c = cities.get(i);
List<Bonus> bonuses = c.getBonus();
for (int j = 0; bonuses != null && j < bonuses.size(); j++) {
Bonus b = bonuses.get(j);
if (b != null)
b.applyBonus(player);
}
}
}
You check if the element is empty like this:
if(array != null && array.get(index) == null) // element is null when empty
To check if the array as a whole is empty (has no elements):
if(array != null && array.isEmpty())
In general the problem in java is chaining getters like this:
getCity().get(j).getBonus().get(i)!=null
You can get nullpointer exception from 4 places here. You can check them all like:
if (getCity()!=null &&
getCity().get(j) &&
getCity().get(j).getBonus() &&
getCity().get(j).getBonus().get(i)!=null){
....
}
Other way could be encapsulating whole code in try - catch and catching NPE, which is more like hack.
I also suggest using foreach instead while and don't store array size in separate variables, because you can always get it using
myArr.getSize()
And also check javadoc about ArrayList constructor:
new ArrayList<City>(cities)
because this is likely not doing what you expect
Short story:
init all ArrayLists in constructor (don't specify size)
use foreach loops
don't put nulls into the arrays
and you should be fine without checking for empty elements
I am trying to write less and less code and I am trying to find a way to prevent crashes.
An example what I have encountered is:
public class MyClass
{
private User user;
public MyClass()
{
// Get user from another class
// Another thread, user can be null for couple of seconds or minutes
// Asynchronous call
user = AnotherClass.getUser();
// start method
go();
}
private void go()
{
// Method 1
// Program it is crashing if user is null
if (user.getId() == 155)
{
// TO DO
}
else
{
System.out.println("User is NOT 155 !");
}
// Method 2
// Program still crashes if user is null
if (user != null && user.getId() == 155)
{
// To do
}
else
{
System.out.println("user is not 155");
}
// Method 3
// Program wont crash, but I write much more code !
if (user != null)
{
if (user.getId() == 155)
{
// To do
}
else
{
System.out.println("User is not 155 !");
}
}
else
{
System.out.println("User is not 155 !");
}
}
}
As you can see, method 3 it's working, but I am writing much more code... What should I do?
Prefer the way Short-circuit evaluation, That is method 2.
when the first argument of the AND function evaluates to false, the overall value must be false;
if (user != null && user.getId() == 155)
{
// To do
}
else
{
System.out.println("user is not 155");
}
That is the most preferable and readable code.
Your assumtions are wrong that method2 crash and method3 works. In the above code if user != null then only user.getId() == 155 executes.
Why not use a null object pattern here, so instead of setting user to be null, set it to a special 'null' case (implementation) of the User object ?
e.g.
user = AnotherClass.getUser();
if (user == null) {
user = new NullUser();
}
(ideally AnotherClass.getUser() would do the null check internally)
In this case
user.getId()
could return a special value (-1 ?) which would never equate to a valid user id. Hence your code will always look like:
if (user.getId() == 155)
The same would apply to other methods on the User object.
It's got to be something inside the block started by this statement:
if (user != null && user.getId() == 155)
That is logically identical to method 3. When the JVM sees that user is null, it should stop evaluating that.
I will say though that I encountered something like this with JVM 1.3, so if you are using a really old JVM that may be it.
I'm trying to iterate through a list using the iterator over my list of Logs. The goal is to search for a logs which contains the same phonenumber, type and date as the new log
However, I get a java.util.NoSuchElementException in my conditional statement. Does anyone know what might cause the problem?
My code
public void addLog(String phonenumber, String type, long date, int incoming, int outgoing)
{
//Check if log exists or else create it.
Log newLog = new Log(phonenumber, type, date, incoming, outgoing);
//Log exists
Boolean notExist = false;
//Iterator loop
Iterator<Log> iterator = logs.iterator();
while (iterator.hasNext())
{
//This is where get the exception
if (iterator.next().getPhonenumber() == phonenumber && iterator.next().getType() == type && iterator.next().getDate() == date)
{
updateLog(newLog, iterator.next().getId());
}
else
{
notExist = true;
}
}
if (notExist)
{
logs.add(newLog);
}
}
You are calling next() a bunch of times in one iteration forcing the Iterator to move to an element that doesn't exist.
Instead of
if (iterator.next().getPhonenumber() == phonenumber && iterator.next().getType() == type && iterator.next().getDate() == date)
{
updateLog(newLog, iterator.next().getId());
...
Use
Log log = iterator.next();
if (log.getPhonenumber() == phonenumber && log.getType() == type && log.getDate() == date)
{
updateLog(newLog, log .getId());
...
Every time you call Iterator#next(), it moves the underlying cursor forward.
I have this function with some dead code, marked by Eclipse.
I have two lines that check a & b. Lines that check b are marked as null.
public int[] runThis(List<Integer> buildIds, List<Integer> scenarios, boolean oflag) {
int rating[] = new int[scenarios.size()];
if(buildIds == null) {
System.out.println("ERROR - Building ID list is null!");
return null;
}
if(scenarios == null) {
System.out.println("ERROR - Scenario list is null!"); //dead
return null; //dead
}
return rating;
}
Why does Ellipse make the two lines as dead? Any help? Thanks very much for your time.
Because you've already called scenarios.size() in your array constructor. This guarantees scenarios isn't null or it will have thrown an exception by that point.
What I am trying to do is save a Move objects into a Vector called topMoves. There will be many Move objects which is why I create the object within the loop.
The pastPriceMap stores prices for stocks at some past time (in this case one minute ago). The currPriceMap stores price for stocks some time within the last second.
I get the following exception:
Exception in thread "Timer-0" java.util.NoSuchElementException
This is the line that is causing the problem:
amove.setInitPrice(pastPriceMap.get(iter.next()));
The code snippet is below. When I do the System.out.println statements I get the expected output:
Iterator<String> iter = sortedTopCodes.iterator();
while(iter.hasNext()){
System.out.println(currPriceMap.get(iter.next()));
System.out.println(pastPriceMap.get(iter.next()));
Move amove = new Move();
amove.setSecCode(iter.next());
amove.setPrice(currPriceMap.get(iter.next()));
amove.setInitPrice(pastPriceMap.get(iter.next()));
topMoves.add(amove);
}
return topMoves;
The Move class looks like this:
private String secCode;
private double price;
private double initPrice;
public String getSecCode() {
return secCode;
}
public void setSecCode(String secCode) {
this.secCode = secCode;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public double getInitPrice() {
return initPrice;
}
public void setInitPrice(double lastPrice) {
this.initPrice = lastPrice;
}
Short answer:
For each call to hasNext() there should be only one call to next()
In your code you have 5 next() with only one hasNext()
Here, read this: http://java.sun.com/javase/6/docs/api/java/util/Iterator.html
EDIT
Longer answer:
Basically an iterator is used to ... well iterate the elements of "something" tipically a collection but it could be anything ( granted that anything returns an Iterator ).
Since you may not know how many elements does that "anything" have, there must be a way to stop iterating right? ( if it was an array, you can tell by the length property, but the iterator is used to "encapsulate" the data structure used in the implementation ) Anyway.
The iterator API defines these two methods
-hasNext(): boolean
-next(): Object ( or <E> since Java 1.5 )
So the typical idiom is this:
while( iterator.hasNext() ) { // reads: while the iterator has next element
Object o = iterator.next(); // give me that element
}
What happens if the iterator has only two items?
while( iterator.hasNext() ) { // the first time will return true, so the next line will be executed.
Object o = iterator.next(); // give me that item. ( 1st element )
Object b = iterator.next(); // oops dangerous by may work ... ( 2nd element )
Object c = iterator.next(); // eeeerhhh... disaster: NoSuchElementException is thrown.
}
This is what is happening to you. You did not verify if the iterator has another element, you just retrieve it. If the iterator happens to have some elements, it may work for a while but there will be a time ( as you just saw ) when it fails.
By the way, DO NOT even think in catching NoSuchElementException. That's a runtime exception and it indicates that something in your code logic should be fixed.
See this answer to know more about the exceptions.
Here is a version using the new for loops:
for ( String secCode : secCodeList ) {
System.out.println(currPriceMap.get(secCode));
System.out.println(pastPriceMap.get(secCode));
Move amove = new Move();
amove.setSecCode(secCode);
amove.setPrice(currPriceMap.get(secCode));
amove.setInitPrice(pastPriceMap.get(secCode));
topMoves.add(amove);
}
in the older fashion :
String secCode = null;
for ( Iterator<String> it = secCodeList.iterator(); it.hasNext() ) {
secCode = it.next();
System.out.println(currPriceMap.get(secCode));
System.out.println(pastPriceMap.get(secCode));
Move amove = new Move();
amove.setSecCode(secCode);
amove.setPrice(currPriceMap.get(secCode));
amove.setInitPrice(pastPriceMap.get(secCode));
topMoves.add(amove);
}
// while there are more lines
while(scanner.hasNextLine())
{
final String line;
final String[] words;
// get the next line
line = scanner.nextLine();
// break the line up into the words (\\s+ should break it up via whitespace)
words = line.split("\\s");
if(words.length != 5)
{
throw new WhateverExceptionMakesSense(line + " must contain 5 words");
}
System.out.println(currPriceMap.get(words[0]));
System.out.println(pastPriceMap.get(words[1]));
Move amove = new Move();
amove.setSecCode(words[2]);
amove.setPrice(currPriceMap.get(words[3]));
amove.setInitPrice(pastPriceMap.get(words[4]));
topMoves.add(amove);
}