Как создать повторно используемое необязательное отображение со ссылками на метод? - PullRequest
0 голосов
/ 06 сентября 2018

Хотя я пытаюсь использовать дополнительные функции со ссылками на методы, меня действительно смутило, как оптимизировать их с помощью повторно используемого кода. Я думаю, что застрял, пытаясь использовать все эти новые функции (для меня) одновременно, я решил избавиться от стиля java-6, теперь я думаю, что не могу думать просто, я чувствую, что он становится слишком сложным. Как я могу создать

List<BooleanExpression> expressionMapping = new ArrayList<>();

    if (request != null) { // request is input parameter, a DTO

        Optional.ofNullable(request.getPlantId())
            .map(campaign.plant.id::contains) // campaign is static created by Querydsl
            .ifPresent(expressionMapping::add);

        Optional.ofNullable(request.getTitle())
            .map(campaign.title::containsIgnoreCase)
            .ifPresent(expressionMapping::add);

        Optional.ofNullable(request.getCampaignNumber())
            .map(this::getLikeWrapped)
            .map(campaign.campaignNumber::like)
            .ifPresent(expressionMapping::add);
... 20 more Optional bunch of code like this
}

также возникают проблемы с написанием этого кода с помощью Optional, как и предыдущие:

if (request.getLockVehicle() != null) {
            if (request.getLockVehicle()) {
                expressionMapping.add(campaign.lockVehicle.isNotNull());
            } else {
                expressionMapping.add(campaign.lockVehicle.isNull());
            }
        }

Ответы [ 2 ]

0 голосов
/ 06 сентября 2018

Как насчет использования enum для объявления всех полей из Request и использования его в качестве общей части кода. Я не проверял, это только для того, чтобы показать мой подход:

public enum RequestField {
    PLANT_ID(Request::getPlantId, (val, campaign) -> campaign.plant.id::contains),
    TITLE(Request::getTitle, (val, campaign) -> campaign.title::containsIgnoreCase),
    CAMPAIGN_NUMBER(Request::getCampaignNumber, (val, campaign) -> campaign.campaignNumber::like),
    // ... more fields here ...
    ;

    private final Function<Request, Optional<Object>> get;
    private final BiFunction<Object, Campaign, BooleanExpression> map;

    RequestField(Function<Request, Object> get, BiFunction<Object, Campaign, BooleanExpression> map) {
        this.get = get.andThen(Optional::ofNullable);
        this.map = map;
    }

    public static List<BooleanExpression> getBooleanExpressions(Request request, Campaign campaign) {
        if (request == null)
            return Collections.emptyList();

        List<BooleanExpression> res = new LinkedList<>();

        for (RequestField field : values())
            field.get.apply(request)
                     .map(r -> field.map.apply(r, campaign))
                     .ifPresent(res::add);

        return res.isEmpty() ? Collections.emptyList() : Collections.unmodifiableList(res);
    }
}

И ваш код клиента будет выглядеть так:

List<BooleanExpression> booleanExpressions = RequestField.getBooleanExpressions(request, campaign);

приписка Ваш последний код может выглядеть следующим образом:

if (request.getLockVehicle() != null)
    expressionMapping.add(request.getLockVehicle() ? campaign.lockVehicle.isNotNull() : campaign.lockVehicle.isNull());
0 голосов
/ 06 сентября 2018

Цель использования Optional - сообщить, кто вызывает этот метод / параметр, что это может быть null.

В первой части вашего кода вы не получаете никаких преимуществ от этого, вы просто переписываете некоторый код, оборачивая его вокруг Optional логики, но, как вы сказали, без какой-либо "многоразовой" цели.

Полезным способом является использование его в качестве возвращаемого значения метода: например, если вы знаете, что ваш title может быть нулевым, вы можете изменить свой геттер как

public Optional<String> getTitle(){
    return Optional.ofNullable(this.title); //I'm guessing the 'title' variable here
}

Это поможет вам: каждый раз, когда вы звоните getTitle(), вы будете знать, что это может быть нулевым, потому что вы получаете Optional<String> вместо String.

Это приведет вас к:

request.getTitle().ifPresent(title-> title.doSomething())
// you can also add something like .orElse("anotherStringValue")

Второй пример может быть переработан как первый, возвращая getLockVehicle() как Optional<Boolean>, даже если я предлагаю здесь установить значение по умолчанию в вашем классе, вероятно, на false ... Optional<Boolean> довольно бессмысленно имхо

Надеюсь, это поможет очистить ваш разум

...