JavaRush /Java блогу /Random-KY /Java 8де циклдерден арылуу
KapChook
Деңгээл
Volga

Java 8де циклдерден арылуу

Группада жарыяланган
Java 8де киргизилген функционалдык стил тилге сонун кошумча болуп саналат. Азыр Java таза OOP эмес, азыр ал OOP жана функционалдык программалоонун гибриди. Бул оюн алмаштыргыч жана биз бул өзгөрүүлөрдү сиңирүү үчүн OOP мээбизди өзгөртүүбүз керек. Java 8 - 1деги циклдерден кутулууБирок эмне үчүн биз бул өзгөртүүлөрдү кабыл алышыбыз керек? Таза OOP аркылуу маселени чече алсак, эмне үчүн функционалдык стил менен тил табышууга убакытты текке кетиришибиз керек?
  • Java 8де киргизилген функционалдык стиль бизнес логикасы менен codeдун ортосундагы ажырымды кыскартууга жардам берет. Бул бизге окуяны табигый агымда жогорку деңгээлде айтууга мүмкүндүк берет. Кандай кылгыңыз келгенин айтуунун ордуна, эмне кылгыңыз келгенин айта аласыз.

  • Код тазараак жана кыскараак болот.

  • Жогорку тартиптеги функциялар бизге:

    • Функцияларды башка функцияларга жөнөтүү
    • Башка функциялардын ичинде функцияларды түзүү
    • Башка функциялардан функцияларды кайтаруу

    Бул Java үчүн чоң утуш, бул үчүн an objectтерди жөнөтүү, түзүү жана кайтаруу керек. Биз ишенимдүү, багытталган жана кайра колдонууга оңой болгон codeду жаза алабыз.

  • Ламбдалардын жардамы менен биз жалкоо эсептөөлөрдү жасай алабыз. Ламбда туюнтмасы методдун аргументи катары жөнөтүлгөндө, компилятор аны методдо чакырганда баалайт. Бул дароо бааланган кадимки ыкма аргументтеринен айырмаланат.

  • Ламбдалар жазуу бирдигинин тесттерин кызыктуу кылат. Алар бизге таза, көлөмү кичинекей жана тез жазыла турган жеңил тесттерди түзүүгө мүмкүндүк берет. Биз lambdas аркылуу текшерorп жаткан codeду түп тамыры менен жок кыла алабыз. Бул ар кандай сценарийлердин codeго кандай таасир этээрин сынап көрүүгө мүмкүнчүлүк берет.

  • Жаңы үлгүлөрдү үйрөнүү.

  • Жана дагы көп нерселер!

Бирок жетиштүү суу, бул макалада биз салттуу циклдердин альтернативалуу чечимдерди карап чыгабыз. Албетте, циклдер ийкемдүү, бирок бул баасы жок болбойт. break, циклдин жүрүм-турумун кескин түрдө өзгөртүп, бизди code эмнеге жетүүгө аракет кылып жатканын түшүнүүгө гана эмес continue, returnциклдин кантип иштээрин түшүнүүгө да мажбурлайт. Эми биз циклдерди кантип кыскараак жана окула турган codeго айландырса болорун карап чыгабыз.

Коддоштуруу башталсын!

Биз макалалар менен иштейбиз. Макаланын аталышы, автору жана бир нече теги бар.
private class Article {

    private final String title;
    private final String author;
    private final List<String> tags;

    private Article(String title, String author, List<String> tags) {
        this.title = title;
        this.author = author;
        this.tags = tags;
    }

    public String getTitle() {
        return title;
    }

    public String getAuthor() {
        return author;
    }

    public List<String> getTags() {
        return tags;
    }
}
Ар бир мисал илмектерди колдонуу менен салттуу чечимди жана Java 8дин жаңы мүмкүнчүлүктөрүн колдонуу менен чечимди камтыйт. Биринчи мисалда биз жыйнактагы биринчи макаланы “Java” теги менен тапкыбыз келет. Келгиле, циклди колдонуу менен чечимди карап көрөлү.
public Article getFirstJavaArticle() {

    for (Article article : articles) {
        if (article.getTags().contains("Java")) {
            return article;
        }
    }
    return null;
}
Эми Stream API'ден операцияларды колдонуу менен маселени чечели.
public Optional<Article> getFirstJavaArticle() {
    return articles.stream()
        .filter(article -> article.getTags().contains("Java"))
        .findFirst();
    }
Абдан сонун, туурабы? filterАдегенде биз "Java" теги менен бардык макалаларды табуу үчүн операцияны колдонобуз , андан кийин биз findFirst()биринчи көрүнүштү алуу үчүн колдонобуз. Агымдар жалкоо болгондуктан жана чыпка агымды кайтарып бергендиктен, бул ыкма элементтерди биринчи дал келгенди тапканга чейин гана иштетет. Эми биринчи эле макаланын ордуна "Java" деп белгиленген бардык макалаларды алалы. Алгач илмектерди колдонуп чечүү.
public List<Article> getAllJavaArticles() {

    List<Article> result = new ArrayList<>();

    for (Article article : articles) {
        if (article.getTags().contains("Java")) {
            result.add(article);
        }
    }
    return result;
}
Агым операцияларын колдонуу менен чечим.
public List<Article> getAllJavaArticles() {
    return articles.stream()
        .filter(article -> article.getTags().contains("Java"))
        .collect(Collectors.toList());
    }
Бул мисалда биз collectколлекцияны жарыялоонун жана дал келген жазууларды ачык кошуунун ордуна, натыйжадагы агымды кыскартуу операциясын колдондук. Азырынча жакшы. Stream API чындап жаркыраган мисалдар үчүн убакыт. Бардык макалаларды автор боюнча топтойлу. Адаттагыдай эле, биз циклдерди колдонуу менен чечүү менен баштайбыз:
public Map<String, List<Article>> groupByAuthor() {

    Map<String, List<Article>> result = new HashMap<>();

    for (Article article : articles) {
        if (result.containsKey(article.getAuthor())) {
            result.get(article.getAuthor()).add(article);
        } else {
            ArrayList<Article> articles = new ArrayList<>();
            articles.add(article);
            result.put(article.getAuthor(), articles);
        }
    }
    return result;
}
Агым операцияларын колдонуу менен бул көйгөйдүн таза жолун таба алабызбы?
public Map<String, List<Article>> groupByAuthor() {
    return articles.stream()
        .collect(Collectors.groupingBy(Article::getAuthor));
}
Укмуш! Операцияны groupingByжана метод шилтемесин колдонуу менен getAuthor()биз таза жана окула турган codeду алабыз. Эми коллекцияда колдонулган тегдердин калганын табалы. Келгиле, циклдин мисалы менен баштайлы:
public Set<String> getDistinctTags() {

    Set<String> result = new HashSet<>();

    for (Article article : articles) {
        result.addAll(article.getTags());
    }
    return result;
}
Макул, агым операцияларын колдонуу менен муну кантип чече аларыбызды карап көрөлү:
public Set<String> getDistinctTags() {
    return articles.stream()
        .flatMap(article -> article.getTags().stream())
        .collect(Collectors.toSet());
}
Баракелде! flatmapтегдердин тизмесин бир жыйынтык агымына түздөөгө жардам берет, биз аны collectкайра кайтаруу топтомун түзүү үчүн колдонобуз.

Чексиз мүмкүнчүлүктөр

Бул илмектерди окула турган code менен алмаштыруунун 4 мисалы болду. Stream API'ди текшерип көрүңүз, анткени бул макала бетти тырмап койгон. Javaнын жаңы функционалдык стorн өздөштүрүү OOP иштеп чыгуучулары үчүн кыйынчылык жаратат, бирок бул жакшы кабыл алынышы керек болгон кыйынчылык. Мен андан ары барып, сиз таза функционалдык программалоо тorн үйрөнүшүңүз керек деп айтам. Ушундай жол менен сиз анын мүмкүнчүлүктөрүн жана күчүн толук түшүнө аласыз. Бул функционалдык программалоону башка деңгээлде түшүнүүгө жардам берет деп ойлойм. Ошентип, жакшы эски OOP менен бирге функционалдык программалоону үйрөнүңүз жана экөөнү тең чоңураак code жазуу үчүн колдонуңуз! Эки макаланын котормолорунун акысыз аралашмасы - Эмне үчүн Java 8де функционалдык программалоону жана Java 8де Swerving Away from Loops программасын кабыл алышыңыз керек
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION