Рейдеры потребителей, поставщиков, предикатов и функций в Java 8

Java

Сегодня мы также поговорим оПотребитель, Поставщик, Предикат, ФункцияИспользование этих интерфейсов, в использовании Java8, хотя эти интерфейсы не используются нагло, они молчат. Почему ты это сказал?

Все эти интерфейсыjava.util.functionПод пакетом они Потребитель (тип потребления), поставщик (тип поставки), предикат (тип предиката), функция (функциональность).Я полагаю, что со следующим объяснением вы должны очень четко понять функцию этого интерфейса.

Тогда давайте поговорим об использовании этого интерфейса из конкретного сценария приложения!

1 Потребительский интерфейс

Буквально мы видим, чтоconsumer接口Это потребительский интерфейс. Он так же прост, как передача параметров, а затем вывод значений. Некоторые методы в Java 8 кажутся очень абстрактными. На самом деле, пока вы понимаете их, они очень просты в использовании и очень просты.

Давайте сначала рассмотрим пример, а затем проанализируем этот интерфейс.

1.1 Экземпляр потребителя

/**
     * consumer接口测试
     */
    @Test
    public void test_Consumer() {
        //① 使用consumer接口实现方法
        Consumer<String> consumer = new Consumer<String>() {

            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        Stream<String> stream = Stream.of("aaa", "bbb", "ddd", "ccc", "fff");
        stream.forEach(consumer);

        System.out.println("********************");

        //② 使用lambda表达式,forEach方法需要的就是一个Consumer接口
        stream = Stream.of("aaa", "bbb", "ddd", "ccc", "fff");
        Consumer<String> consumer1 = (s) -> System.out.println(s);//lambda表达式返回的就是一个Consumer接口
        stream.forEach(consumer1);
        //更直接的方式
        //stream.forEach((s) -> System.out.println(s));
        System.out.println("********************");

        //③ 使用方法引用,方法引用也是一个consumer
        stream = Stream.of("aaa", "bbb", "ddd", "ccc", "fff");
        Consumer consumer2 = System.out::println;
        stream.forEach(consumer);
        //更直接的方式
        //stream.forEach(System.out::println);
    }

выходной результат

1.2 Анализ случая

consumerАнализ интерфейса

В коде ① мы напрямую создаемConsumerинтерфейс и реализуетacceptметод, этот метод является ключом к этому интерфейсу.

Давайте взглянемacceptметод; этот метод передает один параметр и не возвращает значения. когда мы нашлиforEachнужен одинConsumerПри передаче параметра типа может быть выведено соответствующее значение.

② лямбда-выражение как потребитель

Consumer<String> consumer1 = (s) -> System.out.println(s);//lambda表达式返回的就是一个Consumer接口

В приведенном выше коде мы используем следующееlambdaвыражение какConsumer. Если вы внимательно посмотрите, вы найдете,lambdaВозвращаемое значение выражения представляет собойConsumer; так что вы можете понять, почемуforEachМетоды могут принимать лямбда-выражения в качестве параметров.

③ Ссылка на метод как потребитель

Consumer consumer2 = System.out::println;

В приведенном выше коде мы использовалиссылка на методкак Consumer , а также может быть переданforEachметод.

1.3 Другие потребительские интерфейсы

В дополнение к интерфейсу Consumer, использованному выше, также можно использовать следующие интерфейсы Consumer.IntConsumer、DoubleConsumer、LongConsumer、BiConsumer, используйте тот же метод, что и выше.

1.4 Сводка для потребителей

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

① Потребитель — это интерфейс, и пока он реализуетacceptметод, вы можете выводить информацию как «потребитель». ② На самом деле возвращаемые значения лямбда-выражений и ссылок на методыТип потребителя, поэтому их можно использовать какforEachпараметры метода и выводит значение.

2 Интерфейс поставщика

Интерфейс поставщика представляет собойтип питанияИнтерфейс, по сути,контейнер, интерфейс, который может использоваться для хранения данных, а затем использоваться другими методами, хорошо ли вы его понимаете? Если вы все еще не понимаете его, посмотрите на следующий пример, и вы должны понять его досконально!

2.1 Экземпляр поставщика

**
     * Supplier接口测试,supplier相当一个容器或者变量,可以存储值
     */
    @Test
    public void test_Supplier() {
        //① 使用Supplier接口实现方法,只有一个get方法,无参数,返回一个值
        Supplier<Integer> supplier = new Supplier<Integer>() {
            @Override
            public Integer get() {
                //返回一个随机值
                return new Random().nextInt();
            }
        };

        System.out.println(supplier.get());

        System.out.println("********************");

        //② 使用lambda表达式,
        supplier = () -> new Random().nextInt();
        System.out.println(supplier.get());
        System.out.println("********************");

        //③ 使用方法引用
        Supplier<Double> supplier2 = Math::random;
        System.out.println(supplier2.get());
    }

выходной результат

2.2 Анализ случая

① Анализ интерфейса поставщика

Supplier<Integer> supplier = new Supplier<Integer>() {
            @Override
            public Integer get() {
                //返回一个随机值
                return new Random().nextInt();
            }
        };

Глядя на этот код, мы реализуем объект Supplier, создавgetметод, этот метод не имеет параметров и возвращает значение, поэтому каждый раз, когда этот интерфейс используется, значение будет возвращено и сохранено в этом интерфейсе, так что этоконтейнер.

② лямбда-выражение в качестве поставщика

//② 使用lambda表达式,
        supplier = () -> new Random().nextInt();
        System.out.println(supplier.get());
        System.out.println("********************");

В приведенном выше коде мы используемлямбда-выражениеВозвращает интерфейс типа Supplier, а затем мы вызываемgetспособ получить это значение.

③ Ссылка на метод как Поставщик

//③ 使用方法引用
        Supplier<Double> supplier2 = Math::random;
        System.out.println(supplier2.get());

Ссылка на метод также является интерфейсом, который возвращает тип Supplier.

2.3 Экземпляр поставщика 2

После прочтения первого примера у нас должно появиться понимание, и давайте посмотрим на другой.

/**
     * Supplier接口测试2,使用需要Supplier的接口方法
     */
    @Test
    public void test_Supplier2() {
        Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
        //返回一个optional对象
        Optional<Integer> first = stream.filter(i -> i > 4)
                .findFirst();

        //optional对象有需要Supplier接口的方法
        //orElse,如果first中存在数,就返回这个数,如果不存在,就放回传入的数
        System.out.println(first.orElse(1));
        System.out.println(first.orElse(7));

        System.out.println("********************");

        Supplier<Integer> supplier = new Supplier<Integer>() {
            @Override
            public Integer get() {
                //返回一个随机值
                return new Random().nextInt();
            }
        };

        //orElseGet,如果first中存在数,就返回这个数,如果不存在,就返回supplier返回的值
        System.out.println(first.orElseGet(supplier));
    }

выходной результат

анализ кода

Optional<Integer> first = stream.filter(i -> i > 4)
                .findFirst();

Используйте этот метод, чтобы получить необязательный объект, а затем в необязательном объекте есть методы orElse и orElseGet, для которых требуется интерфейс Supplier.

//optional对象有需要Supplier接口的方法
        //orElse,如果first中存在数,就返回这个数,如果不存在,就放回传入的数
        System.out.println(first.orElse(1));
        System.out.println(first.orElse(7));

        System.out.println("********************");

        Supplier<Integer> supplier = new Supplier<Integer>() {
            @Override
            public Integer get() {
                //返回一个随机值
                return new Random().nextInt();
            }
        };

        //orElseGet,如果first中存在数,就返回这个数,如果不存在,就返回supplier返回的值
        System.out.println(first.orElseGet(supplier));
  • orElse: если сначала есть номер, вернуть этот номер, если нет, вернуть входящий номер
  • orElseGet: если сначала есть число, верните число, если нет, верните значение, возвращенное поставщиком.

2.4 Другие интерфейсы поставщиков

В дополнение к интерфейсу Поставщика, использованному выше, также можно использовать следующие интерфейсы Поставщика.IntSupplier 、DoubleSupplier 、LongSupplier 、BooleanSupplier, используйте тот же метод, что и выше.

2.5 Резюме поставщиков

① Интерфейс поставщика можно понимать как контейнер для хранения данных. ② В интерфейсе поставщика естьgetметод, возвращающий значение.

3 Интерфейс предикатов

Интерфейс Predicate — это интерфейс предикатов, по сути, это интерфейс, аналогичный логическому суждением о типе, что будет понято позже.

3.1 Экземпляр предиката

/**
     * Predicate谓词测试,谓词其实就是一个判断的作用类似bool的作用
     */
    @Test
    public void test_Predicate() {
        //① 使用Predicate接口实现方法,只有一个test方法,传入一个参数,返回一个bool值
        Predicate<Integer> predicate = new Predicate<Integer>() {
            @Override
            public boolean test(Integer integer) {
                if(integer > 5){
                    return true;
                }
                return false;
            }
        };

        System.out.println(predicate.test(6));

        System.out.println("********************");

        //② 使用lambda表达式,
        predicate = (t) -> t > 5;
        System.out.println(predicate.test(1));
        System.out.println("********************");

    }

выходной результат

3.2 Анализ случая

① Анализ интерфейса предикатов

//① 使用Predicate接口实现方法,只有一个test方法,传入一个参数,返回一个bool值
        Predicate<Integer> predicate = new Predicate<Integer>() {
            @Override
            public boolean test(Integer integer) {
                if(integer > 5){
                    return true;
                }
                return false;
            }
        };

В этом кодеPredicateобъект интерфейса, где реализующий классtestметод, который должен передать параметр и возвращаетboolзначение, поэтому функция этого интерфейсасудить!

System.out.println(predicate.test(6));

Посмотрите еще раз, вызовите тестовый метод, передайте значение, и он вернет логическое значение.

② Использовать лямбда-выражение в качестве предиката

//② 使用lambda表达式,
        predicate = (t) -> t > 5;
        System.out.println(predicate.test(1));
        System.out.println("********************");

лямбда-выражение возвращаетPredicateинтерфейс, а затем вызватьtestметод!

3.3 Экземпляр интерфейса предиката 2

/**
     * Predicate谓词测试,Predicate作为接口使用
     */
    @Test
    public void test_Predicate2() {
        //① 将Predicate作为filter接口,Predicate起到一个判断的作用
        Predicate<Integer> predicate = new Predicate<Integer>() {
            @Override
            public boolean test(Integer integer) {
                if(integer > 5){
                    return true;
                }
                return false;
            }
        };

        Stream<Integer> stream = Stream.of(1, 23, 3, 4, 5, 56, 6, 6);
        List<Integer> list = stream.filter(predicate).collect(Collectors.toList());
        list.forEach(System.out::println);

        System.out.println("********************");

    }

выходной результат

Этот код сначала создает объект Predicate, а затем реализуетtestметод, сделать вывод в методе испытаний:Возвращает true, если переданный параметр больше 5, иначе возвращает false;

Stream<Integer> stream = Stream.of(1, 23, 3, 4, 5, 56, 6, 6);
        List<Integer> list = stream.filter(predicate).collect(Collectors.toList());
        list.forEach(System.out::println);

Этот код вызываетStreamизfilterметод,filterПараметр, требуемый методом, — это интерфейс Predicate, поэтому здесь, покаданные больше 5будет выводить.

3.4 Обзор интерфейса предикатов

① Предикат — это интерфейс типа предиката, который на самом деле служит только суждением. ② Предикат путем реализацииtestметод судить.

4 Функциональный интерфейс

Функциональный интерфейс — это функциональный интерфейс, одной из его функций является преобразование входных данных в другую форму выходных данных.

4.1 Пример функционального интерфейса

/**
     * Function测试,function的作用是转换,将一个值转为另外一个值
     */
    @Test
    public void test_Function() {
        //① 使用map方法,泛型的第一个参数是转换前的类型,第二个是转化后的类型
        Function<String, Integer> function = new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return s.length();//获取每个字符串的长度,并且返回
            }
        };

        Stream<String> stream = Stream.of("aaa", "bbbbb", "ccccccv");
        Stream<Integer> stream1 = stream.map(function);
        stream1.forEach(System.out::println);

        System.out.println("********************");

    }

выходной результат

4.2 Анализ кода

① Анализ функционального интерфейса

//① 使用map方法,泛型的第一个参数是转换前的类型,第二个是转化后的类型
        Function<String, Integer> function = new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return s.length();//获取每个字符串的长度,并且返回
            }
        };

Этот код создаетFunctionинтерфейсный объект, реализующийapplyметод, этот метод имеет один входной параметр и один выходной параметр. Среди них первый параметр дженерика — это тип до преобразования, а второй — тип после преобразования.

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

② Важный метод карты приложений

 Stream<String> stream = Stream.of("aaa", "bbbbb", "ccccccv");
        Stream<Integer> stream1 = stream.map(function);
        stream1.forEach(System.out::println);

существуетFunctionВажное применение интерфейса должно быть сказаноStreamКатегорияmapметод,mapметод проходит черезFunctionинтерфейс, который возвращает преобразованныйStreamсвоего рода.

4.3 Другие функциональные интерфейсы

В дополнение к функциональному интерфейсу, использованному выше, также могут использоваться следующие функциональные интерфейсы. IntFunction , DoubleFunction , LongFunction , ToIntFunction , ToDoubleFunction , DoubleToIntFunction и т. д. используйте тот же метод, что и выше.

4.4 Краткое описание функционального интерфейса

① Функциональный интерфейс — это функциональный интерфейс, который представляет собой функцию преобразования данных. ② Реализация функционального интерфейсаapplyметод преобразования.

5 Резюме

В предыдущем введении былоConsumer、Supplier、Predicate、FunctionУ меня есть детальное понимание этих интерфейсов.На самом деле, эти интерфейсы не сложные, но немного абстрактные.Если вы поймете больше, то обнаружите, что они очень просты и очень удобны в использовании!

Если в статье есть что-то неуместное, поправьте меня, если вам нравится читать в WeChat, вы также можете подписаться на меня.Публичный аккаунт WeChat:好好学java, доступ к высококачественным учебным ресурсам.