Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Stream and Filter by string Levenshtein distance

I'm trying to figure out if there is an elegant way of doing the following using Java streams:

  1. take a list of Pojos where one of the fields is a String (eg surname)
  2. take a String that you want to search for (eg surnameTypedIn)
  3. find the Pojo in the list with the smallest Levenshtein distance (I'm using the Apache Commons StringUtils.getLevenshteinDistance)
  4. return the whole Pojo, not just the surname or the distance

So far the only way I've been able to do it is to create an intermediate map at each level, which works but feels very dirty. Is there an accepted way to do this, eg by implementing a custom Collector or something like that?

like image 816
Matt Avatar asked Dec 19 '22 06:12

Matt


1 Answers

Just create a Comparator<Pojo>:

Comparator<Pojo> comparator =
    Comparator.comparingInt(
        p -> StringUtils.getLevenshteinDistance(p.surname(), surnameTypedIn)

Then use the Stream.min method:

Optional<Pojo> minPojo = listOfPojos.stream().min(comparator);

(You can inline the Comparator.comparingInt in the Stream.min call if you want; I just separated them for readability).

Or, without streams:

Pojo minPojo = Collections.min(listOfPojos, comparator);

Note that this way will throw a NoSuchElementException if listOfPojos is empty.

like image 84
Andy Turner Avatar answered Jan 17 '23 23:01

Andy Turner