Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Private Sorting Rule in a Stream Java

Hey if anyone has an idea I would be really thankfull. I'm in a Java stream and i would like to sort my list that i'll be returning. I need to sort the list via TradPrefis ( MyObject::getTradPrefix ). But this would be way too easy. Because i want to sort following the number at the end of TradPrefix exampleTradPrefix_[NUMBER TO SORT]

Exemple : hello_1 test_2 ... still_there_22

Here is a piece of code so you can imagine easier.

public LinkedHashSet<WsQuestion> get(String quizId, String companyId) {
    LinkedHashSet<QuizQuestionWithQuestion> toReturn = quizQuestionRepository.findAllQuizQuestionWithQuestionByQuizId(quizId);
    return (toReturn.stream()
            .map(this::createWsQuestion)
            .sorted(comparing(WsQuestion::getTradPrefix.toString().length()))
            .collect(Collectors.toCollection(LinkedHashSet::new)));
}
like image 685
Jules Spender Avatar asked Nov 12 '18 16:11

Jules Spender


3 Answers

One method would simply be to split getTradPrefix().toString() by _ and parse the rightmost value as an int, and use it to sort the Stream:

public LinkedHashSet<WsQuestion> get(String quizId, String companyId) {
    LinkedHashSet<QuizQuestionWithQuestion> toReturn = quizQuestionRepository.findAllQuizQuestionWithQuestionByQuizId(quizId);
    return toReturn.stream()
        .map(this::createWsQuestion)
        .sorted(Comparator.comparingInt(question -> {
            String[] args = question.getTradPrefix().toString().split("_");
            return Integer.parseInt(args[args.length - 1]);
        }))
        .collect(Collectors.toCollection(LinkedHashSet::new));
}
like image 103
Jacob G. Avatar answered Oct 25 '22 07:10

Jacob G.


If I where you I would simply put a method on the WsQuestion class, let's call it sort order:

public int getSortOrder() {
  return Integer.valueOf(tradPrefix.substring(tradPrefix.lastIndexOf("_") + 1));
}

The Integer parse is needed since comparing strings would give "11" < "2" (thanks Holger for pointing this out). The lastIndexOf() makes sure that any number of underscores are allowed in tradPrefix, as long as there is at least one.

Then simply create a comparotor by using Comparator.comparingInt()

public LinkedHashSet<WsQuestion> get(String quizId, String companyId) {
  LinkedHashSet<QuizQuestionWithQuestion> toReturn = quizQuestionRepository.findAllQuizQuestionWithQuestionByQuizId(quizId);
  return (toReturn.stream()
      .map(this::createWsQuestion)
      .sorted(comparingInt(WsQuestion::getSortOrder))
      .collect(Collectors.toCollection(LinkedHashSet::new)));
}
like image 22
Magnilex Avatar answered Oct 25 '22 07:10

Magnilex


You can make a small Comparator like this:

  private static final Comparator<String> questionComparator = Comparator.comparingInt(s -> {
    String[] pieces = s.split("_");
    return Integer.parseInt(pieces[pieces.length-1]);
  });

Then use it in your sorted().

Having a separate Comparator will make your code more readable too, since you will be separating concerns.

return toReturn.stream()
            .map(this::createWsQuestion)
            .sorted(questionComparator)
            .collect(Collectors.toCollection(LinkedHashSet::new));
like image 21
jbx Avatar answered Oct 25 '22 08:10

jbx