Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
134 views
in Technique[技术] by (71.8m points)

java - Looping through ArrayList of object to find the highest value and return the details

I want to create a method which calculates and displays the highest overall crime stats. Eg to output something like:

*City with highest crime stats 204451 is New York

City : New York

State : NY

Population : 8165001

Murder : 596

Robbery : 23511

Assault : 26908

Burglary : 22137

Larceny : 115363

Car theft : 15936

Violent crime : 51015

Possession crime : 153436*

I have one class StartApp.java which the ArrayList of CityCrime type, and it reads the crime stats from a csv file:

    public static ArrayList<CityCrime> crimes = new ArrayList<CityCrime>();
    
    public static void readCrimeData() {
    
    File file = new File("crimeUSA.csv");

    FileReader fileReader;
    BufferedReader bufferedReader;
    String crimeInfo;
    String[] stats;

    try {
        fileReader = new FileReader(file);
        bufferedReader = new BufferedReader(fileReader);

        crimeInfo = bufferedReader.readLine();
        crimeInfo = bufferedReader.readLine();

        do {
            CityCrime crime = new CityCrime(); // Default constructor
            stats = crimeInfo.split(",");
            {
                if(stats[0] != null) {
                crime.setCity(stats[0]);
            }
            if(stats[1] != null) {
                crime.setState(stats[1]);
            }
            if(stats[2] != null) {
                if(Integer.parseInt(stats[2]) >=0) {
                    crime.setPopulation(Integer.parseInt(stats[2]));
                }
            }
            if(stats[3] != null) {
                if(Integer.parseInt(stats[3]) >=0) {
                    crime.setMurder(Integer.parseInt(stats[3]));
                }
            }
            
            if(stats[4] != null) {
                if(Integer.parseInt(stats[4]) >=0) {
                    crime.setRobbery(Integer.parseInt(stats[4]));
                }
            }
            
            if(stats[5] != null) {
                if(Integer.parseInt(stats[5]) >=0) {
                    crime.setAssault(Integer.parseInt(stats[5]));
                }
            }
                
            if(stats[6] != null) {
                if(Integer.parseInt(stats[6]) >=0) {
                    crime.setBurglary(Integer.parseInt(stats[6]));
                }
            }
            
            if(stats[7] != null) {
                if(Integer.parseInt(stats[7]) >=0) {
                    crime.setLarceny(Integer.parseInt(stats[7]));
                }
            }
            
            if(stats[8] != null) {
                if(Integer.parseInt(stats[8]) >=0) {
                    crime.setMotorTheft(Integer.parseInt(stats[8]));
                }
            }
            
        }
            crimes.add(crime);
            System.out.println(crime);

            crimeInfo = bufferedReader.readLine();

        } while (crimeInfo != null);

        fileReader.close();
        bufferedReader.close();

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (NumberFormatException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
    
}

        public static void showMenu() {
    
    Scanner menuSelect = new java.util.Scanner(System.in); 
    System.out.println("1. Display all crime stats by city");
    System.out.println("2. Display all crime stats by selected city");
    System.out.println("3. Display the murder stats by selected state ");
    System.out.println("4. Display  highest crime city - all crimes");
    System.out.println("5. Display each state (in alphabetical order with the number of car thefts ");
    System.out.println("6. Write / export all cities in descending order of Robbery rate ");
    System.out.println("7. Quit");
    System.out.println("Enter option 1-7");
    //int option = menuSelect.nextInt();
    
    Scanner scanner = new Scanner(System.in);
    int option = Integer.parseInt(menuSelect.next());

      switch(option) {
        case 1:
            displayAllCityCrimeStats();
            break;
        case 2:
            System.out.println("Enter city");
            String cityOption = menuSelect.next();
            displayCityByName(cityOption);
            break;
        case 3:
            System.out.println("Enter state");
            String stateOption = menuSelect.next();
            displayMurdersByState(stateOption);
            break;
        case 4:
            //displayHighest();
            displayCityHighestCrimeStats();
            break;
        case 5:
            displayStateCarThefts();
            break;    
        case 6:
            return; // System.exit(0) or quit however you want to
        default:
            option = Integer.parseInt(scanner.next());
        
    }

}

Then in CityCrime.java I have:

    public class CityCrime {


//Instance variables

private String city;
private String state;
private int population;
private int murder;
private int robbery;
private int assault;
private int burglary;
private int larceny;
private int motorTheft;
public int totalCrimes;


public static void main(String[] args) {
    
}

public int getTotalCrimes() {
    return totalCrimes;
}

public int setTotalCrimes(int murder, int robbery, int assault, int burglary, int larceny, int motorTheft) {
    this.totalCrimes = murder + robbery + assault + burglary + larceny + motorTheft;
    return totalCrimes;
}

public String getCity() {
    return city;
}


public void setCity(String city) {
    this.city = city;
}

public String getState() {
    return state;
}


public void setState(String state) {
    if(state.equalsIgnoreCase("ALABAMA")) {
        this.state = "AL";
    }
//etc
}

public int getPopulation() {
    return population;
}


public void setPopulation(int population) {
    this.population = population;

}


public int getMurder() {
    return murder;
}


public void setMurder(int murder) {
    this.murder = murder;
}


public int getRobbery() {
    return robbery;
}


public void setRobbery(int robbery) {
    this.robbery = robbery;

}


public int getAssault() {
    return assault;
}


public void setAssault(int assault) {
    this.assault = assault;

}


public int getBurglary() {
    return burglary;
}


public void setBurglary(int burglary) {
    this.burglary = burglary;

}


public int getLarceny() {
    return larceny;
}


public void setLarceny(int larceny) {
    this.larceny = larceny;
}


public int getMotorTheft() {
    return motorTheft;
}


public void setMotorTheft(int motorTheft) {
    this.motorTheft = motorTheft;

}

public static void showAllMurderDetails() {

    for (CityCrime crime : StartApp.crimes) {
        System.out.println("Crime: City= " + crime.getCity() + ", Murder= " + crime.getMurder());
    }
    System.out.println();
}


public static int showAllViolentCrimes() {
    int total = 0;
    for(CityCrime crime : StartApp.crimes) {
        total=total+crime.getMurder();
        total=total+crime.getRobbery();
        total=total+crime.getAssault();
    }
    System.out.println("Total of violent crimes: " + total);
    return total;
    
}

public static int getPossessionCrimes() {
    int total=0;
    for (CityCrime crime : StartApp.crimes) {
        total = total + crime.getBurglary();
        total = total + crime.getLarceny();
        total = total + crime.getMotorTheft();
    }
    System.out.println("Total of possession crimes: " + total);
    return total;
}

    }

I have tried a lot of different things so far but I just can't seem to figure it out, and I've been deep into the google pages. I'd really appreciate help with this function. I do almost understand why the way I'm trying is not working, as I write it I know it isn't going to work. A couple of what I've tried is the following: (please try to ignore the mess of it-I've changed things 100 times)

        public static void displayHighest() {
    int crimeStatCurrent = 0;
    int crimeStatPrev = 0;
    int crimeStatCurrent1 = 0;
    int highest = 0;
    String highestCity = "";
    boolean flag;
    CityCrime crimeStat = null;
    for(CityCrime crime : crimes) {
        /*
         * crimeStatCurrent = crimeStatCurrent + crime.getAssault();; crimeStatCurrent =
         * crimeStatCurrent + crime.getBurglary(); crimeStatCurrent = crimeStatCurrent +
         * crime.getLarceny(); crimeStatCurrent = crimeStatCurrent +
         * crime.getMotorTheft(); crimeStatCurrent = crimeStatCurrent +
         * crime.getMurder(); crimeStatCurrent = crimeStatCurrent + crime.getRobbery();
         */
        crimeStatCurrent = crime.setTotalCrimes(crime.getMurder(), crime.getRobbery(), crime.getAssault(), crime.getBurglary(), crime.getLarceny(), crime.getMotorTheft());
        if(crime.getTotalCrimes() > crimeStatPrev) {
            highest = crimeStatCurrent;
            highestCity = crime.getCity();
            System.out.println("Highest City" + highestCity);
        }
    }
}




public static void displayCityHighestCrimeStats() {
    int crimeStat = 0;
    int prevCrimeStat = 0;
    int highestCrimeStat = 0;
    int CurrentCrimeStat;
    String highestCity = "";
    int i;
    for(CityCrime crime : crimes) {
        
        /*
         * crimeStat = crimeStat + crime.getAssault();; crimeStat = crimeStat +
         * crime.getBurglary(); crimeStat = crimeStat + crime.getLarceny(); crimeStat =
         * crimeStat + crime.getMotorTheft(); crimeStat = crimeStat + crime.getMurder();
         * crimeStat = crimeStat + crime.getRobbery();
         */
        
        //crimeStat = crime.setTotalCrimes(crime.getMurder(), crime.getRobbery(), crime.getAssault(), crime.getBurglary(), crime.getLarceny(), crime.getMotorTheft());
    
        for(i = 0; i < crimes.size(); i++) {
            if(crime.setTotalCrimes(crime.getMurder(), crime.getRobbery(), crime.getAssault(), crime.getBurglary(), crime.getLarceny(), crime.getMotorTheft()) > prevCrimeStat) {
                highestCity = crime.getCity();
                highestCrimeStat = crime.getTotalCrimes();
            }
            else if(crime.setTotalCrimes(crime.getMurder(), crime.getRobbery(), crime.getAssault(), crime.getBurglary(), crime.getLarceny(), crime.getMotorTheft()) < prevCrimeStat) {
                
            }
            
            prevCrimeStat = crimeStat;
            
        }
        System.out.println("Crime Stat: " + crimeStat + "for " + crime.getCity());
        
        
    }
    //System.out.println("City with highest crime stats is " + highestCity + " with " + crimeStat);
}

Okay, this is the method I have now:

        public CityCrime highestCrimeCity(List<CityCrime> cities) {
    return cities
       // Create a stream from the list of cities
       .stream()
       // Sort by totalCrime in reverse order
       .sorted(Comparator.comparingInt(CityCrime::getTotalCrimes).reversed()      
       // Take the first city if it exists (you could pass an empty array)
       .findFirst()
       // If the city exists return it, otherwise null
       .orElseNull();   
}

for 'FindFirst'


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

My tip is to maintain a clean code:

  • Each method of your code should solve a single task. Code will be easier to read and maintain also by people who never saw it before
  • Try to use logger instead of System.out methods. This give you a lot more flexibility
  • Use existing methods when possible instead of rewriting them. Don't reinvent the wheel
  • Try to use "new" (not really new, it comes in java 8) stream construct when possible. The code will be easier to read and maintain
  • Do not use instances variables when possible, but pass data as parameters. The code will be easier to understand and less affected by side effects

In particular you can do something like that:

// This method just calculate the City with highest crime (single task)
// It takes cities as a parameter, no other data are needed (pass parameters instead of using instance variables)
// It uses stream of java 8 (prefer using stream over loops)
// It uses sorted method (use existing methods when possible)
// It uses Optional
public CityCrime highestCrimeCity(List<CityCrime> cities) {
    return cities
       // Create a stream from the list of cities
       .stream()
       // Sort by totalCrime in reverse order
       .sorted(Comparator.comparingInt(CityCrime::getTotalCrime).reversed()      
       // Take the first city if it exists (you could pass an empty array)
       .findFirst()
       // If the city exists return it, otherwise null
       .orElseNull();   
}
    

Than you can call it to print the output as follow:

 CityCrime badCity = highestCityCrime(cities);
 System.out.println("The baddest city is " + badCity.getCity() + " with " + badCity.getTotalCrimes() + " crimes");

When you configured a logger you can replace the System.out.println with LOGGER.info


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...