nrsmac
nrsmac

Reputation: 105

Populating TreeMap<String, ArrayList(of different lengths) > with <ArrayList> data

My function takes in a Scanner and returns a TreeMap map with Strings as keys, and an ArrayList as a value. These ArrayLists can be of different lengths. I've parsed the Scanner to a new ArrayList textData for easier iteration. The procedure should go as follows:

  1. If the element is a String, have that be the new key to the next TreeMap entry (stored as String state) and clear the temporary array
  2. If the element is parseable to a Double, add it to the temporary ArrayList statePopData.
  3. Commit to map.

Ideally, with the scanner :

"Utah\t6.0\t60\n" + "California\t5\t30\n" + "Nevada\t3"

should return:

{"Utah",[6.0, 60.0], "California",[5.0, 30.0], "Nevada",[3.0],}

Here is what I have thus far:

 public static TreeMap<String, ArrayList<Double>> readTable (Scanner dataSource)
{
        //Parse Scanner to ArrayList
    ArrayList<String> textData = new ArrayList<String>();

    while(dataSource.hasNext()){
        textData.add(dataSource.next());
   }

    //Populate TreeMap
    ArrayList<Double> statePopData = new ArrayList<>();
    TreeMap<String, ArrayList<Double>> map = new TreeMap<>();

    for (int i = 0; i < textData.size(); i++) {

        boolean isDouble;
        String state = "";


      try {
          Double.parseDouble(textData.get(i));
          isDouble = true;
      } catch (NumberFormatException | NullPointerException nfe) {
          isDouble = false;
      }


      if(isDouble) {
          statePopData.add(Double.parseDouble(textData.get(i)));
      } else { //means its a string

          statePopData.clear();
          state = textData.get(i);
      } 

      if (statePopData.isEmpty()) {
          map.put(state, statePopData);
      }

    } return map;}

I feel confident with the pieces, but I can never seem to run the map.put() statement at the right time with the proper values to commit. For example, my current results of the program are: {California=[3.0], Nevada=[3.0], Utah=[3.0]}

EDIT: The linked answer doesn't involve any implementation nor fully answers what I'm trying to do.

Upvotes: 1

Views: 714

Answers (1)

boot-and-bonnet
boot-and-bonnet

Reputation: 761

Looks like duplicate code to Failed test case, what am I doing wrong?
The same ArrayList instance is being modified and set for each state, so it is being cleared and overwritten each time. A simpler approach may be:

    TreeMap<String, ArrayList<Double>> map = new TreeMap<>();
    while (dataSource.hasNext()) {
        String state = dataSource.next();
        Double d = Double.parseDouble(dataSource.next());
        map.computeIfAbsent(state, k -> new ArrayList<>()).add(d);
    }
    return map;

Updated solution for state followed by multiple numbers:

// Usually better to use List than ArrayList for declared generic types
public static TreeMap<String, List<Double>> readTable(Scanner dataSource) {
    TreeMap<String, List<Double>> map = new TreeMap<>();
    String state = null;
    while (dataSource.hasNext()) {
        String next = dataSource.next(); // Should never be null
        try {
            Double d = Double.parseDouble(next);
            // Ignores numbers received before state is set
            if (state != null)
                // If state has been set, list that must have been initialized
                map.get(state).add(d); 
        } catch (NumberFormatException e) {
            // Assumes any non-double is a state
            state = next;
            // Initialize map entry with empty list
            map.put(state, new ArrayList<>());
        }
    }
    return map;
}

Upvotes: 1

Related Questions