Re[2]: Pattern-matching in Java
От: AJ Великобритания  
Дата: 26.04.19 15:07
Оценка: 9 (1)
Здравствуйте, C0s, Вы писали:

C0s>пример учебный? (это я к тому, чтобы не писать дурацких вопросов "зачем и кто это сделал так?")


Учебный, ага. В реальности я пытаюсь написать плагин к IntelliJ который разбирает дерево из PsiElement'ов и обрабатывает определённые куски кода.

C0s>
    
C0s>// как-то так, наверное
C0s>return input.filter(Pair.class::isInstance).map(Pair.class::cast).filter(isLeftInteger).filter(isRightInteger)
C0s>            .mapToInt(p -> ((Integer) p.left) + ((Integer) p.right)).sum();

AJ>>    }
C0s>


C0s>потенциально, если облегчить условие суммирования до "всех найденных Integer'ов даже в несимметричных по типу парах", то можно было бы сразу после map(cast) сделать разворот в

C0s>
C0s>flatMap(p -> Stream.concat(p.left, p.right)).filter(Integer.class::isInstance).map(Integer.class::cast).mapToInt(Integer::intValue)
C0s>


Спасибо, буду знать про cast. Облегчить условие в реальном случае не выйдет.

Накопал тут либу https://www.vavr.io/ с которой решение выглядит следующим образом

import java.util.Arrays;
import java.util.stream.Stream;

import static io.vavr.API.*;
import static io.vavr.Predicates.*;

public class Main {

    public static void main(String[] args) {
        Stream<Object> input = Arrays.stream(new Object[] {
            "ABC", 1, Pair.of(3, 4), Pair.of(1, "2"), Pair.of(2, 3), "TEST"
        });
        System.out.println(process(input));
    }
    
    public static int process(Stream<Object> input) {
        return input.map(Main::sumIfPairOfInts).mapToInt(Integer::valueOf).sum();
    }
    
    public static Integer sumIfPairOfInts(Object object) {
        return Match(object).of(
                Case(MyPatterns.$Pair($(instanceOf(Integer.class)), $(instanceOf(Integer.class))), (left, right) -> left + right),
                Case($(), () -> 0));
    }
}


Класс ниже процессится их кодо-генератором через Maven
import io.vavr.Tuple;
import io.vavr.Tuple2;
import io.vavr.match.annotation.Patterns;
import io.vavr.match.annotation.Unapply;

@Patterns
class My {

    @Unapply
    static <L, R> Tuple2<L, R> Pair(Pair<L, R> pair) {
        return Tuple.of(pair.left, pair.right);
    }    
}


На выходе получается вот такая штуковина
// @formatter:off
// CHECKSTYLE:OFF
import io.vavr.API.Match.Pattern;
import io.vavr.API.Match.Pattern2;

// GENERATED BY VAVR <<>> derived from My

@SuppressWarnings("deprecation")
public final class MyPatterns {

    private MyPatterns() {
    }

    public static <L, R, _1 extends L, _2 extends R> Pattern2<Pair<L, R>, _1, _2> $Pair(Pattern<_1, ?> p1, Pattern<_2, ?> p2) {
        return Pattern2.of(Pair.class, p1, p2, My::Pair);
    }

}
// CHECKSTYLE:ON
// @formatter:on


public class Pair<L, R> {
    
    L left;
    R right;
    
    static <L, R> Pair<L, R> of(L left, R right) {
        Pair<L, R> pair = new Pair<>();
        pair.left = left;
        pair.right = right;
        return pair;
    }
}
Отредактировано 26.04.2019 16:34 AJ . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.