Search code examples
javalistsortingcomparelistiterator

How to iterate through a list of objects, convert a field, compare it, then sort by that field?


I am having an issue where I believe I have to combine several concepts that I am reading about, but I can't seem to figure out a way to combine them that makes sense, or what would be most efficient. Here is my situation:

I am working with microservices which is why this is so oddly specific. Essentially I am getting a list of Volume objects from another service. A volume object contains three fields, a String type, a String date(which actually represents time in the format "HH:mm", blame the data modelers for the naming conventions), and an int close.

What I am trying to do is to take this list of objects and sort by date(time), then create a new list of objects which will contain the same dates(times), but will have different field values based off of calculations I am doing. In order to sort by time, I believe I need to convert the time fields to Date objects and then compare those. I'm struggling how to iterate through the objects and compare the converted fields. Something that I feel like has put me on the right path is this: How to sort a List<Object> alphabetically using Object name field

But I can't seem to get that to work. Here's my code:

volumeResources.sort(volumeResources, new Comparator<VolumeResource>(){
        @Override
        public int compare(VolumeResource v1, VolumeResource v2) {
            SimpleDateFormat format = new SimpleDateFormat("HH:mm");
            try {
                Date d1 = format.parse(v1.getDate());
                Date d2 = format.parse(v2.getDate());
            } catch (ParseException e) {
                log.error("Error in parsing string to date. ", e);
            }
            return d1.compareTo(d2);
        }
    });

Now right off the bat, I know that this must be incorrect because I started comparing the VolumeResources v1 and v2, but instead tried to compare the dates at the end. In place of the return statement above, I have also tried the one below, but I don't think that will always work because it's not actually setting the formatted object to a Date object:

return format.parse(v1.getDate()).compareTo(format.parse(v2.getDate()));

So that's where I'm lost. This seems like a fairly simple need when described in pseudocode, but I can't seem to figure out how to make it work functionally. Bonus points if there's a way I can populate the other fields I need easily from this. Double bonus points for using lambdas or helping me make this efficient.

Thanks for any and all help everyone.


Solution

  • If you are using Java 8 and above the sorting by time (which is represented as String) may look like this:

        volumeResources.sort(new Comparator<VolumeResource>() {
            @Override
            public int compare(VolumeResource v1, VolumeResource v2) {
                return v1.getDate().compareTo(v2.getDate());
            }
        });
    

    Prior Java 8 it should look like:

        Collections.sort(volumeResources, new Comparator<VolumeResource>() {
            @Override
            public int compare(VolumeResource v1, VolumeResource v2) {
                return v1.getDate().compareTo(v2.getDate());
            }
        });
    

    Using lambda:

        volumeResources.sort((v1, v2) -> v1.getDate().compareTo(v2.getDate()));
    

    Assuming that volumeResources is a populated mutable List (not null) and all entries have date field populated properly with a well formed time (no spaces, tabs, or missing leading 0)

    Explanation

    According to your definition of date field it is naturally sortable as a string, you do not need to convert them into java Date class.

    Your example has an issue by using Java 8 sort method defined in List interface in a manner how it used to be prior Java 8 by using utility class Collections - this is wrong, you do not need to supply collection as a first parameter.