Mam listę niestandardowych podmiotów, z których chcę zabiegać pola za pomocą metody, i że chcę filtrować dalej. Jestem dość nowy w Java strumieni, I nie wiem, czy lepiej używać mapy i filtrów lub użyć bardziej tradycyjnej forEach. Oto moja pierwsza próba:

public List<Restaurant> findRestaurantsWithin(Double latitude, Double longitude, Integer radius) {
    log.info("Searching restaurants {} km to point {} lat., {} long.", radius, latitude, longitude);

    List<Restaurant> restaurants = this.restaurantRepository.findAll();

    restaurants.forEach(restaurant ->
        {
            if (restaurant.getLatitude() != null) {
                restaurant.setDistance(
                        this.getDistance(Double.parseDouble(restaurant.getLatitude()),
                                Double.parseDouble(restaurant.getLongitude()), latitude, longitude)
                );
            }
        }
    );

    return restaurants.stream()
            .filter(restaurant -> restaurant.getDistance() <= radius)
            .sorted(Comparator.comparing(Restaurant::getDistance))
            .skip(size * page - 1)
            .limit(size)
            .collect(Collectors.toList());

A oto drugi:

return this.restaurantRepository.findAll().stream()
                .filter(restaurant ->
                {
                    if (restaurant.getLatitude() != null) {
                        Double distance = this.getDistance(Double.parseDouble(restaurant.getLatitude()), Double.parseDouble(restaurant.getLongitude()), latitude, longitude);
                        if (distance <= radius) {
                            restaurant.setDistance(distance);
                            return true;
                        }
                    }
                    return false;
                })
                .sorted(Comparator.comparing(Restaurant::getDistance))
                .skip(size * page - 1)
                .limit(size)
                .collect(Collectors.toList());

Na drugim powinienem najpierw użyć .map, ale nie jestem pewien, czy będzie różnica w wydajności. Czy jest lepsza praktyka lub bardziej elegancki sposób na to? Dzięki !

0
Alain Duguine 20 lipiec 2020, 14:24

1 odpowiedź

Najlepsza odpowiedź

Powiedziałbym, że Restaunt::setDistance jest tutaj dużym zapachem kodu. Każda restauracja jest zdolna do trzymania nieruchomości, która mówi, jak daleko jest z innego dowolnego punktu. Nie wiemy, gdzie lub co ten punkt jest lub kiedy został ustawiony. To nie jest prawdziwa nieruchomość restauracji, to tylko hack.

Skutki uboczne i programowanie funkcjonalne w ogóle nie mieszają się dobrze, co jest kolejnym powodem, dla którego oba przykłady mogą wydawać się niebezpieczne dla Ciebie.

Oto jak to zrobił, z ogólnym przeznaczeniem Pair klasa (istnieje wiele, ale dokładna implementacja nie powinna mieć znaczenia. Java FX został usunięty, myślę Java 11, ale jeśli używasz wersji Java przed tym, javafx.util.Pair nie wymaga zależności)

return restaurantRepository.findAll().stream()
    .filter(restaurant -> restaurant.getLatitude() != null)
    .map(restaurant -> new Pair<>(restaurant, this.getDistance(/*blah blah*/)))
    .filter(resAndDistance -> resAndDistance.getValue() <= radius)       
    .sorted(Comparator.comparing(Pair::getValue))
    .skip(size * page - 1)
    .limit(size)
    .collect(Collectors.toList());
3
Michael 20 lipiec 2020, 11:42