Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Java Fundamentals

You're reading from   Java Fundamentals A fast-paced and pragmatic introduction to one of the world's most popular programming languages

Arrow left icon
Product type Paperback
Published in Mar 2019
Publisher
ISBN-13 9781789801736
Length 408 pages
Edition 1st Edition
Languages
Arrow right icon
Authors (5):
Arrow left icon
Miles Obare Miles Obare
Author Profile Icon Miles Obare
Miles Obare
Basheer Ahamed Fazal Basheer Ahamed Fazal
Author Profile Icon Basheer Ahamed Fazal
Basheer Ahamed Fazal
Rogério Theodoro de Brito Rogério Theodoro de Brito
Author Profile Icon Rogério Theodoro de Brito
Rogério Theodoro de Brito
Gazihan Alankus Gazihan Alankus
Author Profile Icon Gazihan Alankus
Gazihan Alankus
Vinicius Isola Vinicius Isola
Author Profile Icon Vinicius Isola
Vinicius Isola
+1 more Show less
Arrow right icon
View More author details
Toc

Table of Contents (12) Chapters Close

Java Fundamentals
Preface
1. Introduction to Java FREE CHAPTER 2. Variables, Data Types, and Operators 3. Control Flow 4. Object-Oriented Programming 5. OOP in Depth 6. Data Structures, Arrays, and Strings 7. The Java Collections Framework and Generics 8. Advanced Data Structures in Java 9. Exception Handling Appendix

Lesson 7: The Java Collections Framework and Generics


Activity 27: Read Users from CSV Using Array with Initial Capacity

Solution:

  1. Create a class called UseInitialCapacity with a main() method

    public class UseInitialCapacity {
      public static final void main (String [] args) throws Exception {
      }
    }
  2. Add a constant field that will be the initial capacity of the array. It will also be used when the array needs to grow:

    private static final int INITIAL_CAPACITY = 5;
  3. Add a static method that will resize arrays. It receives two parameters: an array of Users and an int that represents the new size for the array. It should also return an array of Users. Implement the resize algorithm using System.arraycopy like you did in the previous exercise. Be mindful that the new size might be smaller than the current size of the passed in array:

    private static User[] resizeArray(User[] users, int newCapacity) {
      User[] newUsers = new User[newCapacity];
      int lengthToCopy = newCapacity > users.length ? users.length : newCapacity;
      System.arraycopy(users, 0, newUsers, 0, lengthToCopy);
      return newUsers;
    }
  4. Write another static method that will load the users from a CSV file into an array. It needs to ensure that the array has the capacity to receive the users as they are loaded from the file. You'll also need to ensure that after finishing loading the users, the array do not contain extra slots at the end:

    public static User[] loadUsers(String pathToFile) throws Exception {
      User[] users = new User[INITIAL_CAPACITY];
    
      BufferedReader lineReader = new BufferedReader(new FileReader(pathToFile));
      try (CSVReader reader = new CSVReader(lineReader)) {
        String [] row = null;
        while ( (row = reader.readRow()) != null) {
          // Reached end of the array
          if (users.length == reader.getLineCount()) {
            // Increase the array by INITIAL_CAPACITY
            users = resizeArray(users, users.length + INITIAL_CAPACITY);
          }
    
          users[users.length - 1] = User.fromValues(row);
        } // end of while
      
        // If read less rows than array capacity, trim it
        if (reader.getLineCount() < users.length - 1) {
          users = resizeArray(users, reader.getLineCount());
        }
      } // end of try
      
      return users;
    }
  5. In the main method, call the load users method and print the total number of users loaded:

    User[] users = loadUsers(args[0]);
    System.out.println(users.length);
  6. Add imports:

    import java.io.BufferedReader;
    import java.io.FileReader;

    The output is as follows:

    27

Activity 28: Reading a Real Dataset Using Vector

Solution:

  1. Before starting, change your CSVLoader to support files without headers. To do that, add a new constructor that receives a boolean that tells if it should ignore the first line or not:

    public CSVReader(BufferedReader reader, boolean ignoreFirstLine) throws IOException {
      this.reader = reader;
      if (ignoreFirstLine) {
        reader.readLine();
      }
    }
  2. Change the old constructor to call this new one passing true to ignore the first line. This will avoid you to go back and change any existing code:

    public CSVReader(BufferedReader reader) throws IOException {
      this(reader, true);
    }
  3. Create a class called CalculateAverageSalary with main method:

    public class CalculateAverageSalary {
      public static void main (String [] args) throws Exception {
      }
    }
  4. Create another method that reads data from the CSV and load the wages into a Vector. The method should return the Vector at the end:

    private static Vector loadWages(String pathToFile) throws Exception {
      Vector result = new Vector();
      FileReader fileReader = new FileReader(pathToFile);
      BufferedReader bufferedReader = new BufferedReader(fileReader);
      try (CSVReader csvReader = new CSVReader(bufferedReader, false)) {
        String [] row = null;
        while ( (row = csvReader.readRow()) != null) {
          if (row.length == 15) { // ignores empty lines
            result.add(Integer.parseInt(row[2].trim()));
          }
        }
      }
      return result;
    }
  5. In the main method, call the loadWages method and store the loaded wages in a Vector. Also store the initial time that the application started:

    Vector wages = loadWages(args[0]);
    long start = System.currentTimeMillis();
  6. Initialize three variables to store the min, max and sum of all wages:

    int totalWage = 0;
    int maxWage = 0;
    int minWage = Integer.MAX_VALUE;
  7. In a for-each loop, process all wages, storing the min, max and adding it to the sum:

    for (Object wageAsObject : wages) {
      int wage = (int) wageAsObject;
      totalWage += wage;
      if (wage > maxWage) {
        maxWage = wage;
      }
      if (wage < minWage) {
        minWage = wage;
      }
    }
  8. At the end print the number of wages loaded and total time it took to load and process them. Also print the average, min and max wages:

    System.out.printf("Read %d rows in %dms\n", wages.size(), System.currentTimeMillis() - start);
    System.out.printf("Average, Min, Max: %d, %d, %d\n", totalWage / wages.size(), minWage, maxWage);
  9. Add imports:

    import java.io.BufferedReader;
    import java.io.FileReader;
    import java.util.Vector;

    The output is as follows:

    Read 32561 rows in 198ms
    Average, Min, Max: 57873, 12285, 1484705

Activity 29: Iterating on Vector of Users

Solution:

  1. Create a new class called IterateOnUsersVector with main method:

    public class IterateOnUsersVector {
      public static void main(String [] args) throws IOException {
      }
    }
  2. In the main method, call the UsersLoader.loadUsersInVector passing the first argument passed from the command line as the file to load from and store the data in a Vector:

    Vector users = UsersLoader.loadUsersInVector(args[0]);
  3. Iterate over the users Vector using a for-each loop and print the information about the users to the console:

    for (Object userAsObject : users) {
      User user = (User) userAsObject;
      System.out.printf("%s - %s\n", user.name, user.email);
    }
  4. Add imports:

    import java.io.IOException;
    import java.util.Vector;

    The output is as follows:

    Bill Gates - [email protected]
    Jeff Bezos - [email protected]
    Marc Benioff - [email protected]
    Bill Gates - [email protected]
    Jeff Bezos - [email protected]
    Sundar Pichai - [email protected]
    Jeff Bezos - [email protected]
    Larry Ellison - [email protected]
    Marc Benioff - [email protected]
    Larry Ellison - [email protected]
    Jeff Bezos - [email protected]
    Bill Gates - [email protected]
    Sundar Pichai - [email protected]
    Jeff Bezos - [email protected]
    Sundar Pichai - [email protected]
    Marc Benioff - [email protected]
    Larry Ellison - [email protected]
    Marc Benioff - [email protected]
    Jeff Bezos - [email protected]
    Marc Benioff - [email protected]
    Bill Gates - [email protected]
    Sundar Pichai - [email protected]
    Larry Ellison - [email protected]
    Bill Gates - [email protected]
    Larry Ellison - [email protected]
    Jeff Bezos - [email protected]
    Sundar Pichai - [email protected]

Activity 30: Using a Hashtable to Group Data

Solution:

  1. Create a class called GroupWageByEducation with a main method:

    public class GroupWageByEducation {
      public static void main (String [] args) throws Exception {
      }
    }
  2. Create a static method that creates and returns a Hashtable with keys of type String and values of type Vector of Integers:

    private static Hashtable<String, Vector<Integer>> loadWages(String pathToFile) throws Exception {
      Hashtable<String, Vector<Integer>> result = new Hashtable<>();
      return result;
    }
  3. Between creating the Hashtable and returning it, load the rows from the CSV ensuring they have the correct format:

    FileReader fileReader = new FileReader(pathToFile);
    BufferedReader bufferedReader = new BufferedReader(fileReader);
    try (CSVReader csvReader = new CSVReader(bufferedReader, false)) {
      String [] row = null;
      while ( (row = csvReader.readRow()) != null) {
        if (row.length == 15) {
        }
      }
    }
  4. In the if inside the while loop, get the education level and wage for the record:

    String education = row[3].trim();
    int wage = Integer.parseInt(row[2].trim());
  5. Find the Vector in the Hashtable that corresponds to the current education level and add the new wage to it:

    // Get or create the vector with the wages for the specified education
    Vector<Integer> wages = result.getOrDefault(education, new Vector<>());
    wages.add(wage);
    // Ensure the vector will be in the hashtable next time
    result.put(education, wages);
  6. In the main method, call your loadWages method passing the first argument from the command line as the file to load the data from:

    Hashtable<String,Vector<Integer>> wagesByEducation = loadWages(args[0]);
  7. Iterate on the Hashtable entries using a for-each loop and for each entry, get the Vector of the corresponding wages and initialize min, max and sum variables for it:

    for (Entry<String, Vector<Integer>> entry : wagesByEducation.entrySet()) {
      Vector<Integer> wages = entry.getValue();
      int totalWage = 0;
      int maxWage = 0;
      int minWage = Integer.MAX_VALUE;
    }
  8. After initializing the variables, iterate over all wages and store the min, max and sum values:

    for (Integer wage : wages) {
      totalWage += wage;
      if (wage > maxWage) {
        maxWage = wage;
      }
      if (wage < minWage) {
        minWage = wage;
      }
    }
  9. Then, print the information found for the specified entry, which represents an education level:

    System.out.printf("%d records found for education %s\n", wages.size(), entry.getKey());
    System.out.printf("\tAverage, Min, Max: %d, %d, %d\n", totalWage / wages.size(), minWage, maxWage);
  10. Add imports:

    import java.io.BufferedReader;
    import java.io.FileReader;
    import java.util.Hashtable;
    import java.util.Map.Entry;
    import java.util.Vector;

    The output is as follows:

    1067 records found for education Assoc-acdm
            Average, Min, Max: 193424, 19302, 1455435
    433 records found for education 12th
            Average, Min, Max: 199097, 23037, 917220
    1382 records found for education Assoc-voc
            Average, Min, Max: 181936, 20098, 1366120
    5355 records found for education Bachelors
            Average, Min, Max: 188055, 19302, 1226583
    51 records found for education Preschool
            Average, Min, Max: 235889, 69911, 572751
    10501 records found for education HS-grad
            Average, Min, Max: 189538, 19214, 1268339
    168 records found for education 1st-4th
            Average, Min, Max: 239303, 34378, 795830
    333 records found for education 5th-6th
            Average, Min, Max: 232448, 32896, 684015
    576 records found for education Prof-school
            Average, Min, Max: 185663, 14878, 747719
    514 records found for education 9th
            Average, Min, Max: 202485, 22418, 758700
    1723 records found for education Masters
            Average, Min, Max: 179852, 20179, 704108
    933 records found for education 10th
            Average, Min, Max: 196832, 21698, 766115
    413 records found for education Doctorate
            Average, Min, Max: 186698, 19520, 606111
    7291 records found for education Some-college
            Average, Min, Max: 188742, 12285, 1484705
    646 records found for education 7th-8th
            Average, Min, Max: 188079, 20057, 750972
    1175 records found for education 11th
            Average, Min, Max: 194928, 19752, 806316

Activity 31: Sorting Users

Solution:

  1. Write a comparator class to compare Users by ID:

    import java.util.Comparator;
    public class ByIdComparator implements Comparator<User> {
      public int compare(User first, User second) {
        if (first.id < second.id) {
          return -1;
        }
        if (first.id > second.id) {
          return 1;
        }
        return 0;
      }
    }
  2. Write a comparator class to compare Users by email:

    import java.util.Comparator;
    public class ByEmailComparator implements Comparator<User> {
      public int compare(User first, User second) {
        return first.email.toLowerCase().compareTo(second.email.toLowerCase());
      }
    }
  3. Write a comparator class to compare Users by name:

    import java.util.Comparator;
    public class ByNameComparator implements Comparator<User> {
      public int compare(User first, User second) {
        return first.name.toLowerCase().compareTo(second.name.toLowerCase());
      }
    }
  4. Create a new class called SortUsers with a main method which loads the unique users keyed by email:

    public class SortUsers {
      public static void main (String [] args) throws IOException {
        Hashtable<String, User> uniqueUsers = UsersLoader.loadUsersInHashtableByEmail(args[0]);
      }
    }
  5. After loading the users, transfer the users into a Vector of Users to be able to preserve order since Hashtable doesn't do that:

    Vector<User> users = new Vector<>(uniqueUsers.values());
  6. Ask the user to pick what field he wants to sort the users by and collect the input from standard input:

    Scanner reader = new Scanner(System.in);
    System.out.print("What field you want to sort by: ");
    String input = reader.nextLine();
  7. Use the input in a switch statement to pick what comparator to use. If the input is not valid, print a friendly message and exit:

    Comparator<User> comparator;
    switch(input) {
      case "id":
        comparator = newByIdComparator();
        break;
      case "name":
        comparator = new ByNameComparator();
        break;
      case "email":
        comparator = new ByEmailComparator();
        break;
      default:
        System.out.printf("Sorry, invalid option: %s\n", input);
        return;
    }
  8. Tell the user what field you're going to sort by and sort the Vector of users:

    System.out.printf("Sorting by %s\n", input);
    Collections.sort(users, comparator);
  9. Print the users using a for-each loop:

    for (User user : users) {
      System.out.printf("%d - %s, %s\n", user.id, user.name, user.email);
    }
  10. Add imports:

    import java.io.IOException;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.Hashtable;
    import java.util.Scanner;
    import java.util.Vector;

    The output is as follows:

    5 unique users found.
    What field you want to sort by: email
    Sorting by email
    30 - Jeff Bezos, [email protected]
    50 - Larry Ellison, [email protected]
    20 - Marc Benioff, [email protected]
    40 - Sundar Pichai, [email protected]
    10 - Bill Gates, [email protected]
lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image