Home > Net >  sorting algorithm with nested object
sorting algorithm with nested object

Time:01-19

Hello to all java gurus from a novice java developer, help me write a sorting algorithm for an object that is nested in another object, but at the same time must take into account the field of the main object

main object:

public class Review {
    String date;
    Update update;
}

update object:

public class Update {
    String date;
}

My wrong algorithm:

public class Test {
    public static void main(String[] args) {
        Review review = new Review();
        Update update = new Update();
        update.date = LocalDateTime.now().toString();
        review.date = LocalDateTime.now().minusDays(20L).toString();
        review.update = update;

        Review review1 = new Review();
        Update update1 = new Update();
        update1.date = LocalDateTime.now().minusDays(5L).toString();
        review1.date = LocalDateTime.now().minusDays(30L).toString();
        review1.update = update1;

        Review review10 = new Review();
        Update update10 = new Update();
        update10.date = LocalDateTime.now().minusDays(1L).toString();
        review10.date = LocalDateTime.now().minusDays(100L).toString();
        review10.update = update10;

        Review review2 = new Review();
        review2.date = LocalDateTime.now().minusDays(40L).toString();

        Review review3 = new Review();
        review3.date = LocalDateTime.now().minusDays(50L).toString();

        Review review4 = new Review();
        review4.date = LocalDateTime.now().minusDays(2L).toString();

        List<Review> reviews = List.of(review, review1, review2, review3, review4, review10);

        Comparator<Review> reviewComparator = Comparator.comparing(review5 -> review5.date);

        System.out.println(reviews = reviews.stream().sorted(reviewComparator.reversed()).collect(Collectors.toList()));

        for (int i = 0; i < reviews.size(); i  ) {
            Review review5 = reviews.get(i);
            for (int z = 1; z < reviews.size(); z  ) {
                if (z >= i) {
                    Review review6 = reviews.get(z);
                    if (review6.update != null) {
                        LocalDateTime date1 = LocalDateTime.parse(review6.update.date);
                        LocalDateTime date2 = LocalDateTime.parse(review5.date);
                        int i1 = date1.compareTo(date2);
                        if (i1 > 0) {
                            reviews.remove(review6);
                            reviews.add(i, review6);
                        } else if (review5.update != null) {
                            LocalDateTime date3 = LocalDateTime.parse(review6.update.date);
                            LocalDateTime date4 = LocalDateTime.parse(review5.update.date);
                            int i2 = date3.compareTo(date4);
                            if (i2 > 0) {
                                reviews.remove(review6);
                                reviews.add(i, review6);
                            }
                        }
                    }
                }
            }
        }
        System.out.println(reviews);
    }
}

and result:

[
 Review{date='2022-10-11T13:17:01.754934500', update=Update{date='2023-01-18T13:17:01.754934500'}}, 
 Review{date='2022-12-20T13:17:01.754934500', update=Update{date='2023-01-14T13:17:01.754934500'}}, 
 Review{date='2022-12-30T13:17:01.754934500', update=Update{date='2023-01-19T13:17:01.753935600'}}, 
 Review{date='2023-01-17T13:17:01.754934500', update=null}, 
 Review{date='2022-12-10T13:17:01.754934500', update=null}, 
 Review{date='2022-11-30T13:17:01.754934500', update=null}
]

I expect:

[
 Review{date='2022-12-30T13:17:01.754934500', update=Update{date='2023-01-19T13:17:01.753935600'}}, 
 Review{date='2022-10-11T13:17:01.754934500', update=Update{date='2023-01-18T13:17:01.754934500'}}, 
 Review{date='2023-01-17T13:17:01.754934500', update=null}, 
 Review{date='2022-12-20T13:17:01.754934500', update=Update{date='2023-01-14T13:17:01.754934500'}}, 
 Review{date='2022-12-10T13:17:01.754934500', update=null}, 
 Review{date='2022-11-30T13:17:01.754934500', update=null}
]

CodePudding user response:

So you want to sort by Review.update.date if it exists and Review.date if it doesn't?

You can add that mapping in the key extractor function you're passing to Comparator.comparing(...):

Comparator.comparing(r -> r.update != null ? r.update.date : r.date);

Using this with Collections.sort(reviews, reviewComparator.reversed()); should result in the following list (I added my own toString to make it easier to read):

Review [date=2022-12-30T12:13:27.102934100, update=2023-01-19T12:13:27.096938200]
Review [date=2022-10-11T12:13:27.103934400, update=2023-01-18T12:13:27.103934400]
Review [date=2023-01-17T12:13:27.103934400, update=null]
Review [date=2022-12-20T12:13:27.102934100, update=2023-01-14T12:13:27.102934100]
Review [date=2022-12-10T12:13:27.103934400, update=null]
Review [date=2022-11-30T12:13:27.103934400, update=null]

Note: depending on your design it might make sense to add a method into Review that returns the last review date. I won't change too much of your code (like using proper date types) but it could look like this:

public class Review {
  String date; //creation date
  Update update;

  public String getLastReviewDate() {
    return update != null ? update.date : date;
  }
}

Then the comparator would look like this: Comparator.comparing(Review::getLastReviewDate). It's easier to read and understand that the sorting is based on the virtual property "last review date".

  • Related