Vodet
Vodet

Reputation: 1519

Sort ArrayList by search keyword

I have an ArrayList with This values

"Babel"
"Isabelle"
"Elon"
"Eloise"

I'm typing "el" on the search, I sort the list and I would like to have this result

"Eloise"
"Elon"
"Babel"
"Isabelle"

Because "Eloise" start with my search "el" like "Elon" and then "Babel" because alphabetically is before "Isabelle"

I don't know how to sort by the firsts chars of the array I try to substring names

  users.sort((o1, o2) -> {
                         String name1 = o1.getNickname();
                         String name2 = o2.getNickname();
                         if (o1.getNickname().length() >= finalS.length()) {
                               name1 = o1.getNickname().substring(0, finalS.length());
                         }
                         if (o2.getNickname().length() >= finalS.length()) {
                               name2 = o2.getNickname().substring(0, finalS.length());
                         }
                         return name1.compareTo(name2);
                        });

But this return name1.compareTo(name2); compare the cutted String and order alphabetical. I try to add this below the substring

   if (name1.contains(finalS)) return 1;

or

    if (name2.contains(finalS)) return 1;

nothing work Babel is always at the first position

Upvotes: 1

Views: 161

Answers (2)

Holger
Holger

Reputation: 298143

In most cases, the factory methods in the Comparator interface are suitable and allow to reduce the redundancy of applying operations to both arguments of the comparator.

Since your input is "el" but the names start with an uppercase letter, you want a case insensitive partial matching, followed by sorting by the strings’ natural order.

List<String> users = Arrays.asList("Babel", "Isabelle", "Elon", "Eloise");
String finalS = "el";

users.sort(Comparator.comparing(
    (String u) -> !finalS.regionMatches(true, 0, u, 0, finalS.length()))
    .thenComparing(Comparator.naturalOrder()));

users.forEach(System.out::println);
Eloise
Elon
Babel
Isabelle

Since apparently there’s a class User whose Nickname property you want to compare, the complete sorting code would look like

users.sort(Comparator.comparing(User::getNickname, Comparator.comparing(
    (String u) -> !finalS.regionMatches(true, 0, u, 0, finalS.length()))
    .thenComparing(Comparator.naturalOrder())));

Upvotes: 4

Aura Lee
Aura Lee

Reputation: 466

Your Comparator should look kind of like this: Sorts those which start with your search first, then those which only contain them. But the best way for searching would be to use diff-match-patch (https://github.com/google/diff-match-patch).

 public int compare(User o1, User o2) {
    String search = YOUR_SEARCH.toLowerCase();
    String name1 = o1.getNickname().toLowerCase();
    String name2 = o2.getNickname().toLowerCase();

    int i = Boolean.compare(name2.startsWith(search), name1.startsWith(search));
    if (i != 0)
      return i;
    i = Boolean.compare(name2.contains(search), name1.contains(search));
    if (i != 0)
      return i;
    return name2.compareTo(name1);
  }

Upvotes: 2

Related Questions