javadata-structureshashmapstoring-data

Store the data from text file to a hashmap


I am trying to read a text file and store with a hashmap. The file contains information like this:

1946-01-12;13:00:00;0.3;G 
1946-01-12;18:00:00;-2.8;G
1946-01-13;07:00:00;-6.2;G 
1946-01-13;13:00:00;-4.7;G
1946-01-13;18:00:00;-4.3;G 
1946-01-14;07:00:00;-1.5;G
1946-01-14;13:00:00;-0.2;G

I want to store the dates as keys and then "13:00:00;0.3;G" as value, where 13:00 is time, 0.3 is temperature and G represent a quality code. I wonder if this is even possbile since many rows in the file has the same date? I already wrote a code for storing the data in a list, but now I want to store it in a map instead. My old code looks like this:

/**
 * Provides methods to retrieve temperature data from a weather station file.    
 */
public class WeatherDataHandler {

        private List<Weather> weatherData = new ArrayList<>();

        public void loadData(String filePath) throws IOException {
            List<String> fileData = Files.readAllLines(Paths.get("filepath"));
            for(String str : fileData) {
                List<String> parsed = parseData(str);
                LocalDate date = LocalDate.parse(parsed.get(0));
                LocalTime time = LocalTime.parse(parsed.get(1));
                double temperature = Double.parseDouble(parsed.get(2));
                String quality = parsed.get(3);
                
                //new Weather object
                Weather weather = new Weather(date, time, temperature, quality);
                weatherData.add(weather);       
            }
        }

        private List<String> parseData(String s) {
            return Arrays.asList(s.split(";"));
        }

I got stuck when implementing the hashmap. I started with some code below, but I do not know how to loop over a sequence of dates. What is the simplest way to store the data from the file in a map?

public class WeatherDataHandler {
            public void loadData(String filePath) throws IOException {
                Map<LocalDate, String> map =new HashMap<LocalDate, String>();
                BufferedReader br = new BufferedReader(new FileReader("filepath"));
            String line="";
            int i=0;
            while (line != null) {
                line = br.readLine();
                map.put(i,line);
                i++;
            }
                String date="";
                String time="";
                String temperature="";
                String quality="";
                for(int j=0;j<map.size();j++){
                    if(!(map.get(j)== null)){
                        String[] getData=map.get(j).toString().split("\\,");
                        date = getData[0];
                        time = getData[1];
                        temperature = getData[2];
                        quality = getData[3];
                    }
                }
            }

Solution

  • Using the stream API you can create a map where the key is the date and the [map] value is a list.

    import java.io.IOException;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.util.List;
    import java.util.Map;
    import java.util.stream.Collectors;
    
    public class WeatherDataHandler {
        public static void main(String[] args) {
            Path path = Paths.get("filepath");
            try {
                Map<String, List<String>> map =  Files.lines(path)
                                                      .collect(Collectors.groupingBy(line -> line.split(";", 2)[0]));
                map.entrySet()
                   .stream()
                   .forEach(entry -> System.out.printf("%s = %s%n", entry.getKey(), entry.getValue()));
            }
            catch (IOException x) {
                x.printStackTrace();
            }
        }
    }
    

    Method lines() in class java.nio.file.Files creates a stream where each stream element is a single line of the file being read.
    Method split() splits the line into a two element array (because of the second argument which is the number 2).
    The first array element, i.e. the date, becomes the [map] key and the rest of the line becomes the [map] value.
    Whenever a duplicate key is encountered, the value is appended to the existing value creating a list. Hence the type parameters for the map are String for the [map] key and List<String> for the [map] value.

    Running the above code on your sample data yields:

    1946-01-14 = [1946-01-14;07:00:00;-1.5;G, 1946-01-14;13:00:00;-0.2;G]
    1946-01-12 = [1946-01-12;13:00:00;0.3;G , 1946-01-12;18:00:00;-2.8;G]
    1946-01-13 = [1946-01-13;07:00:00;-6.2;G , 1946-01-13;13:00:00;-4.7;G, 1946-01-13;18:00:00;-4.3;G ]