Программирование на Java и Коллекции Eclipse в субботу вечером.

Вы когда-нибудь просто садились и пишете код?

Иногда мне просто нравится сесть перед своей IDE и написать код Java. Я не всегда знаю, что собираюсь написать, и если обнаружу, что не создаю ничего полезного, я просто брошу работу. В других случаях я обнаруживаю, что создаю что-то, что могло бы стать новым кодовым ката или потенциально новым полезным API.

В субботу вечером я начал писать код и решил, что хочу посмотреть, смогу ли я использовать примитивные API в Коллекциях Eclipse для быстрого и плавного создания алфавита с прописными и строчными буквами.

@Test
public void alphabet()
{
    var alphabet = IntInterval.fromTo('A', 'Z')
            .zipInt(IntInterval.fromTo('a', 'z'))
            .collect(i -> Strings.toCodePoints(
                    i.getOne(),
                    i.getTwo()))
            .makeString(",");
    Assert.assertEquals(
            "Aa,Bb,Cc,Dd,Ee,Ff,Gg,Hh,Ii,Jj,Kk,Ll,Mm,Nn," +
                    "Oo,Pp,Qq,Rr,Ss,Tt,Uu,Vv,Ww,Xx,Yy,Zz",
            alphabet);
}

Я изначально не так писал код. Я начал кодировать с JDK 8 с использованием промежуточных типов, а затем переключился на JDK 11, чтобы использовать var. Исходная версия кода выглядела так.

@Test
public void alphabet()
{
    IntInterval uppercase = IntInterval.fromTo('A', 'Z');
    IntInterval lowercase = IntInterval.fromTo('a', 'z');
    ImmutableList<IntIntPair> pairs = uppercase.zipInt(lowercase);
    ImmutableList<CodePointAdapter> strings =
            pairs.collect(pair ->
                    Strings.toCodePoints(
                            pair.getOne(),
                            pair.getTwo()));
    String alphabet = strings.makeString(",");
    Assert.assertEquals(
            "Aa,Bb,Cc,Dd,Ee,Ff,Gg,Hh,Ii,Jj,Kk,Ll,Mm,Nn," +
                    "Oo,Pp,Qq,Rr,Ss,Tt,Uu,Vv,Ww,Xx,Yy,Zz",
            alphabet);
}

После замены всех типов на var код выглядел следующим образом.

IntelliJ помогает сделать вещи действительно ясными и простыми при использовании свободного стиля программирования в Java, показывая промежуточные типы справа. См. Текст, подчеркнутый зеленым цветом ниже. Использование JDK 11 здесь не имеет большого значения, поскольку var всего на три символа короче, чем String.

Свободные примитивы

Наличие свободного примитивного API делает кодирование с примитивными типами намного более увлекательным и продуктивным. В приведенных выше примерах я смог использовать IntInterval для создания как прописных, так и строчных букв. Затем, используя метод zipInt, я смог объединить два экземпляра IntInterval в ImmutableList из IntIntPair. Затем я смог преобразовать IntIntPair экземпляров в CodePointAdapter экземпляры, используя метод сбора. CodePointAdapter реализует интерфейс CharSequence, который также реализуется классом String в Java. Наконец, makeString(“,”) создает разделенные запятыми String, объединяющие все CodePointAdapter экземпляры.

Здесь требовалось ограниченное количество боксов, когда мне приходилось создавать экземпляры IntIntPair и CodePointAdapter. Но мне ни разу не пришлось помещать какие-либо int значения в их Integer аналоги-оболочки, чтобы продолжить плавные вызовы.

Предпочтение ссылки на метод

Я предпочитаю ссылки на методы лямбдам в Java. Ссылки на методы часто более краткие, чем лямбды, и обычно самодокументируются. Мне пришлось использовать лямбда, чтобы преобразовать IntIntPair в CodePointAdapter с помощью Strings.toCodePoints.

Интересно, стоит ли добавлять новый перегруженный метод toCodePoints к классу Strings, который принимает IntIntPair в качестве параметра. Мне также интересно, стоит ли добавлять версию метода, которая также принимает IntIterable. Прямо сейчас toCodePoints принимает массив int.

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

Возможно, в следующий раз, когда я буду писать код в субботу вечером, я посмотрю, есть ли смысл добавить один или оба toCodePoints служебных метода к классу Strings в Eclipse Collections.

Воскресный вечер подходит для ведения блога и программирования

Я думал, что закончу писать блог в воскресенье вечером, но потом решил, что хочу попробовать дополнительное кодирование с использованием Java и Streams. Мне было любопытно посмотреть, смогу ли я придумать такое же плавное решение для создания алфавита в верхнем / нижнем регистре с использованием примитивных потоков Java. Мне не удалось сохранить все в одном беглом вызове, но это было лучшее решение, которое я мог придумать, используя только встроенные типы Java и API.

Последние мысли

В будущем я мог бы превратить эти примеры кода в новую ката кода для Eclipse Collections и Java Streams. А пока вот окончательные версии кода в виде необработанного текста, если вы хотите поэкспериментировать с API самостоятельно.

Версия коллекций Eclipse

@Test
public void alphabet()
{
    var alphabet = IntInterval.fromTo('A', 'Z')
            .zipInt(IntInterval.fromTo('a', 'z'))
            .collect(this::toCodePoints)
            .makeString(",");
    Assert.assertEquals(
            "Aa,Bb,Cc,Dd,Ee,Ff,Gg,Hh,Ii,Jj,Kk,Ll,Mm,Nn," +
                    "Oo,Pp,Qq,Rr,Ss,Tt,Uu,Vv,Ww,Xx,Yy,Zz",
            alphabet);
}

private CodePointAdapter toCodePoints(IntIntPair pair)
{
    return Strings.toCodePoints(pair.getOne(), pair.getTwo());
}

Версия Java Streams

@Test
public void alphabetStream()
{
    var upper = IntStream.rangeClosed('A', 'Z').toArray();
    var lower = IntStream.rangeClosed('a', 'z').toArray();
    var alphabet = IntStream.range(0, 26)
            .mapToObj(i ->
                    new String(new int[]{upper[i], lower[i]}, 0, 2))
            .collect(Collectors.joining(","));
    Assert.assertEquals(
            "Aa,Bb,Cc,Dd,Ee,Ff,Gg,Hh,Ii,Jj,Kk,Ll,Mm,Nn," +
                    "Oo,Pp,Qq,Rr,Ss,Tt,Uu,Vv,Ww,Xx,Yy,Zz",
            alphabet);
}

Удачного кодирования!

Коллекции Eclipse открыты для взносов. Если вам нравится библиотека, вы можете сообщить нам об этом, отметив ее на GitHub.