Home > Mobile >  Efficiently matching two Flux
Efficiently matching two Flux

Time:07-09

I have two Flux with 2 different data types as shown below:

Flux<Dog> dogs = loadDogsFromFile()
Flux<Man> men = loadMenFromFile()

data class Dog(
    val name: String,
    val ownerName: String,
)


data class Man(
    val name: String,
    val dogOwnerName: String,
)

As you can see the one field we can use to match these two Flux objects is dogOwnerName. Right now this is how I am comparing them

val disposable = dogs.flatMap { dog ->
    men.map { man->
        val isEqual = comparator(dog, man)
        Triple(dog, man, isEqual)
    }
}.filter {x -> x.third === true }

This gets the job done but it is nowhere efficient, it keeps looping even after the desired fields are found and because of that, we have to use a filter operator to only get what we need.

Edit

Based on @marstran comment on the user input, I have large JSON files that contain dogs and men that I'm loading here:

Flux<Dog> dogs = loadDogsFromFile()
Flux<Man> men = loadMenFromFile()

After matching the dogs to their owners/men I'm building an object that I'm saving to the database like this:

val disposable = dogs.flatMap { dog ->
    men.map { man->
        val isEqual = comparator(dog, man)
        Triple(dog, man, isEqual)
    }
}.filter {x -> x.third === true }
 .map{(dog,man,isEqual) ->
  DogOwner(man,dog) 
}.doOnNext{dogOwner -> dogOwnerRepository.save(dogOwner)}

CodePudding user response:

Consider using method take(long n, boolean limitRequest) from Flux:

public final Flux<T> take(long n,
                          boolean limitRequest)
Take only the first N values from this Flux, if available.

using it will allow you to break iterating over man once owner would be found. https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Flux.html#take-long-boolean-

Take a look at this java example. I assume that dog and his owner have same value.

 @Test
    void dog_owner_test() {
        int COUNT = 10000;
        Flux<Integer> dogs = Flux.range(0, COUNT);
        Flux<Integer> man = Flux.range(0, COUNT);

        dogs.flatMap(
            dog ->
                man.map(m -> Tuples.of(dog, m))
                    .filter(tuple -> tuple.getT1().equals(tuple.getT2()))
                    .map(tuple -> new DogOwner(tuple.getT1(), tuple.getT2()))
                    .take(1, true)
        )
            .doOnNext(System.out::println)
            // here you can save DogOwner to db
            .as(StepVerifier::create)
            .expectNextCount(COUNT)
            .verifyComplete();
    }

    private static class DogOwner {
        DogOwner(Integer dog, Integer owner) {
            this.dog = dog;
            this.owner = owner;
        }

        Integer dog;
        Integer owner;

        @Override
        public String toString() {
            return "DogOwner{"  
                "dog="   dog  
                ", owner="   owner  
                '}';
        }
    }
  • Related