Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Что Java 8 нам готовит

Anna | 3.06.2014 | нет комментариев
Пройдемся по новинкам и покодируем по-новому.

Выходит, начнем по списку.

Возможен имеерся список.

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);

Сейчас припомним как мы итерировали в ветхие времена:

for (int i = 0; i < numbers.size(); i  ){
 System.out.println(numbers.get(i));
}

Все здорово, но уж дюже легко оступиться и поставить <= место < либо начать с 1 взамен 0. В вышеприведенном коде мы всецело контролируем механику, мы удерживаем в голове все движущие части. Это отлично во многих случаях, и никто у нас этого не отобрал в Java 7, только добавили сахарку.

for(int num:numbers){
 System.out.println(num);
}

В Java 8, по-бывшему ничего не отбирают, но предлагают «декларативный» подход, значит, мы декларируем что мы хотим сделать, а всю механику — возлагаем на JVM.

 numbers.forEach(value -> System.out.println(value));

Подметим что в примере применяется лямбда-выражение. О нем в дальнейшем абзаце. Многие теснее видели forEach во многих языках и библиотеках. Выходит, forEach нам разрешает в одной строке выразить: «вот тебе коллекция, примени-ка данное выражение ко каждому ее элементам» (декларативный подход), а не: «начиная с первого, и заканчивая последним, пеербери один за иным и используй всякий элемент».

Сейчас о лямбда выражениях.

Дюже аппетитное новшество, разрешающее заменить неизвестные классы на функции.

разглядим пример, теснее приведенный выше:

 numbers.forEach(value -> System.out.println(value));

если бы не было ламбда-выражений, то даный пример выглядел бы так:

numbers.forEach(new Consumer<Integer>() {
 @Override
 public void accept(Integer integer) {
 System.out.println(integer);
 }

 @Override
 public Consumer<Integer> andThen(Consumer<? super Integer> after) {

 return null;
 }
});

Сложновато, не так ли. Но возвратимся к простому однострочному выражению, и тут все еще дозволено кое-что упростить: для чего нам упоминать value двукратно, если выходит ясно, что никакой другий переменной там быть не может.

numbers.forEach(System.out::println);

Да-да мы передали статический способ в качестве функции. Таким образом мы сказали: «вот тебе способ, примени его в цикле».

Вот еще пару примерчиков замены неизвестных классов функциями:

Создание потока:

new Thread(SomeClass::runSomething).start();

Сортировка с компаратором

Collections.sort(numbers, (o1, o2)->-o1.compareTo(o2));
Метаморфозы в Collections Framework

Поразмявшись лямбда-выражениями, перейдем к новинкам в Collections Framework. Возможен нам необходимо пощитать сумму всех чисел в списке, умноженных на два. Недолго думая, мы создаем ломтик кода:

        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);

        int sum = 0;
        for (int num : numbers) {
            sum  = num * 2;
        }

Сейчас обратимся к декларативному подходу:

int result = numbers.stream().
        mapToInt(value->value*2).
        sum();

Постойте-ка, не map-reduce ли это? Он самый. Разберем попорядку. Выходит mapToInt проводит map операцию, в итоге которой элементы становятся умноженными на два. sum — это reduce реформирование, доступное лишь для целых чисел.

Возможен, поступил заказ модифицировать код и обрабатывать лишь четные, а нечетные отфильтровывать.

        System.out.println(numbers.stream().
                filter(value -> value % 2 == 0).
                mapToInt(value -> value * 2).
                sum());

сейчас напротив, нечетные щитать, а четные выбросить:

        System.out.println(numbers.stream().
                filter(value -> value % 2 != 0).
                mapToInt(value -> value * 2).
                sum());
еще одна новая специфика языка

Мы привыкли что интерфейс нам говорит «что мы будем делать», но ничего не делает сам. В Java 8 интерфейс изредка что-то делает.

Вот вам примерчик:

public interface IFly {
    public void takeOff();
    public default void cruise() {
        System.out.println("IFly.cruise");
    };
    public void turn();
    public void land();
}

Кто программировал на С и читал Бьерна Стауструпа, тот задаст вопрос: «а как же diamond problem?». Вопрос увлекательный. И результат есть.

Возможен, класс наследует два интерфейса и в всяком из них есть default способ. При компиляции возникнет оплошность.

    public interface A {
        default void hello() { System.out.println("Hello World from A"); }
    }
    public interface B {
        default void hello() { System.out.println("Hello World from B");
    }
    public class D implements A,B {}

Разберем иной пример: треугольник

    public interface A {
        default void hello() { System.out.println("Hello World from A"); }
    }
    public interface B extends A {
        default void hello() { System.out.println("Hello World from B"); }
    }
    public class C implements B, A {
        public static void main(String... args) {
            new C().hello();
        }
    }

В данном случае победит ближайший в иерархии, тоесть интерфейс B. Ну а если хочется применять способ интерфейса А — то необходимо очевидно указать

A.super.hello();

Разберем 3-й пример: есть конфликтующий способ у абстрактного класса и интерфейса. Правило — побеждает неизменно класс.

Таким образом задача решена:

  • если конфлик на одном ярусе иерархии — компилятор не даст сему случиться
  • если на различных ярусах — победит ближайший
  • если интерфейс вопреки класса — побеждает класс
Еще пару вкусняшек

Base64, как длинно компилятор нам выдавал суровые сообщения об устаревшем sun.misc.Base64 и доводилось пользовать апачевские библиотеки для легкой, казалось бы, вещи.
сейчас вопрос решен: java.util.Base64

Base64.getEncoder().encode(new byte[]{1, 2, 3, 4, 5});

Новейший API по работе с датами и подчас. Если кому не подуше ветхий добросердечный GregorianCallendar, то можете испробовать новые классы Clock, Time, LocalTime

        import java.time.LocalDate;
        import java.time.Period; 
...

        LocalDate time = LocalDate.now();

        Period period = Period.ofDays(2);
        LocalDate newDate = time.plus(period);

        System.out.println("year:" newDate.getYear());
        System.out.println("month:" newDate.getMonth());
        System.out.println("day:" newDate.getDayOfMonth());

 

 Источник: programmingmaster.ru
Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB