Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Functional Programming: Java 8 application using lambda and streams. NO expressi

ID: 3829346 • Letter: F

Question

Functional Programming: Java 8 application using lambda and streams. NO expressions such as while or for loops

Objective: Reads two input files: One file which stores information about the counties, states, zip code. And the other file stores information about people's firstName, lastName, income, zipcode. Narrow the information down to Virginia (“VA”), calculate the average income in each county, and then print all people along with their income relative to their county average.

Note: The input will consist of two text files. The paths to these files (first: counties, second: people) should be passed to the java application using command-line arguments,

e.g. java javaFileName counties.txt people.txt

Files Example:

Counties file: Each line consists of three pieces of information describing a zip-code area, separated by commas: COUNTY,STATE_ABBREV,ZIPCODE For example (counties.txt):

Henrico,VA,23229

Henrico,VA,23228

Richmond,VA,23284

Greensboro,NC,27214

.

.

People file: Each line consists of four pieces of information describing a person, separated be commas: FIRST_NAME,LAST_NAME,INCOME,ZIPCODE

For example (peoples.txt):

John,Doe,10000,23228

Jane,Doe,20000,23228

John,Smith,30000,23229

Mike,Morris,40000,23284

Nancy,Nansemond,50000,23284

Rick,Radon,60004,23229

Ben,Brown,60000,27214

Note: Income will be a positive integer. The combination (First Name, Family Name, ZIP code) will uniquely describe each line, i.e., there will be no two lines that have the same all three of the above. However, there may be e.g. two people with the same first and last names in two different ZIP code in the same county.

Output

No usage of loops such as while, for, do loops. Only streams and lambdas in Java 8.

For each person that lives in Virginia one line should be produced on the output (System out. It should contain four pieces of information FIRST NAME LAST NAME RELATIVE INCOME COUNTY, in that order, separated by a single space. Relative income should be rounded to the nearest integer before printing. The order of people should be: decreasing order of relative income if tie, alphabetical order by family name if still tie, alphabetical order by first name if still tie, alphabetical order by county

Explanation / Answer

Main.java

-----------------------------------------------------------------------------------------------------------------------------------

package com.lambda;

import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Main {
   public static void main(String[] args) {
      
       System.out.println("Enter county file");
       //get the country file
       Scanner scanner = new Scanner(System.in);
       String countryFile = scanner.nextLine();
       List<String> countryList = new ArrayList<>();
       List<String> peopleList = new ArrayList<>();
       try{
           //seperate records by lines
           Stream<String> stream = Files.lines(Paths.get(countryFile));
           countryList = stream.collect(Collectors.toList());
           //get the file with people details
           System.out.println("Enter people file");
           scanner = new Scanner(System.in);
           String peopleFile = scanner.nextLine();
           //seperate records by lines
           stream = Files.lines(Paths.get(peopleFile));
           peopleList = stream.collect(Collectors.toList());
           scanner.close();
       }catch (Exception e) {
           // TODO: handle exception
       }
       List<Person> persons = new ArrayList<>();
       //get each record and split it using comma, set it to person object
       peopleList.forEach(obj->{
           String[] vals = obj.split(",");
           Person p = new Person();
           p.setFirstName(vals[0]);
           p.setLastName(vals[1]);
           p.setIncome(Integer.parseInt(vals[2]));
           p.setZipcode(Long.parseLong(vals[3]));
           persons.add(p);
       });
       //get each record and split it using comma, set it to country object
       List<County> countries = new ArrayList<>();
       countryList.forEach(obj->{
           String[] vals = obj.split(",");
           County c = new County();
           c.setCounty(vals[0]);
           c.setState_abrev(vals[1]);
           c.setZipcode(Long.parseLong(vals[2]));
           countries.add(c);
       });
      
       //filter the people based on zip code , find the average country income and set it in country object
       countries.forEach(country -> {
           int sum = persons.stream().filter(p -> p.getZipcode() == country.getZipcode()).mapToInt(p -> p.getIncome()).sum();
           int count = (int)persons.stream().filter(p -> p.getZipcode() == country.getZipcode()).count();
           country.setAverageIncome(sum/count);
       });
              
       //filter the people based on zip code , set updated income
       countries.forEach(country -> {
           List<Person> person = persons.stream().filter(p -> p.getZipcode() == country.getZipcode()).collect(Collectors.toList());
           persons.removeAll(person);
           person.forEach(per -> {
               per.setIncome(per.getIncome() - country.getAverageIncome());
               per.setCounty(country.getCounty());
               persons.add(per);
           });
          
       });
      
       //set sorting (income decreasing), family name, first name and then country
       Comparator<Person> comparator = Comparator.comparing(Person::getIncome).reversed().thenComparing(Person::getLastName).thenComparing(Person::getFirstName).thenComparing(Person::getCounty);
       Collections.sort(persons,comparator);
       persons.forEach(person -> {
           System.out.println(person.getFirstName()+" "+person.getLastName()+" "+person.getIncome()+" "+person.getCounty());
       });      
      
   }
}

--------------------------------------------------------------------------------------------------------

Person.java

----------------------------------------------------------------------------------------------------------

package com.lambda;

public class Person {
   private String firstName;
   private String lastName;
   private int income;
   private long zipcode;
   private String county;
  
   public Person(String firstName, String lastName, int income, long zipcode, String country) {
       super();
       this.firstName = firstName;
       this.lastName = lastName;
       this.income = income;
       this.zipcode = zipcode;
       this.county = country;
   }

   public Person() {
       // TODO Auto-generated constructor stub
   }
  
   public String getFirstName() {
       return firstName;
   }
   public void setFirstName(String firstName) {
       this.firstName = firstName;
   }
   public String getLastName() {
       return lastName;
   }
   public void setLastName(String lastName) {
       this.lastName = lastName;
   }
   public int getIncome() {
       return income;
   }
   public void setIncome(int income) {
       this.income = income;
   }


   public long getZipcode() {
       return zipcode;
   }

   public void setZipcode(long zipcode) {
       this.zipcode = zipcode;
   }

   public String getCounty() {
       return county;
   }

   public void setCounty(String country) {
       this.county = country;
   }
  
  
}

------------------------------------------------------------------------------------------------

County.java

------------------------------------------------------------------------------------------------

package com.lambda;

public class County {
   private String county;
   private String state_abrev;
   private long zipcode;
   private int averageIncome;
  
   public County(String county, String state_abrev, long zipcode, int relativeIncome) {
       super();
       this.county = county;
       this.state_abrev = state_abrev;
       this.zipcode = zipcode;
       this.averageIncome = relativeIncome;
   }
   public County() {
       // TODO Auto-generated constructor stub
   }
   public String getCounty() {
       return county;
   }
   public void setCounty(String county) {
       this.county = county;
   }
   public String getState_abrev() {
       return state_abrev;
   }
   public void setState_abrev(String state_abrev) {
       this.state_abrev = state_abrev;
   }
   public long getZipcode() {
       return zipcode;
   }
   public void setZipcode(long zipcode) {
       this.zipcode = zipcode;
   }
   public int getAverageIncome() {
       return averageIncome;
   }
   public void setAverageIncome(int relativeIncome) {
       this.averageIncome = relativeIncome;
   }
  
  
}

---------------------------------------------------------------------------------------------

people.txt

-----------------------------------------------------------------------------------------------

John,Doe,10000,23228
Jane,Doe,20000,23228
John,Smith,30000,23229
Mike,Morris,40000,23284
Nancy,Nansemond,50000,23284
Rick,Radon,60004,23229
Ben,Brown,60000,27214

----------------------------------------------------------------------------------------------

counties.txt

----------------------------------------------------------------------------------------------

Henrico,VA,23229
Henrico,VA,23228
Richmond,VA,23284
Greensboro,NC,27214