-
הסגנון הפונקציונלי שהוצג ב-Java 8 עוזר לנו לצמצם את הפער בין ההיגיון העסקי לקוד. היא מאפשרת לנו לספר את הסיפור בזרימה טבעית ברמה גבוהה יותר. במקום להגיד איך אתה רוצה לעשות את זה, אתה יכול להגיד מה שאתה רוצה לעשות.
-
הקוד הופך נקי ותמציתי יותר.
-
פונקציות מסדר גבוה מאפשרות לנו:
- שלח פונקציות לפונקציות אחרות
- צור פונקציות בתוך פונקציות אחרות
- החזר פונקציות מפונקציות אחרות
זהו ניצחון גדול עבור Java, שם אנחנו צריכים לשלוח, ליצור ולהחזיר אובייקטים כדי לעשות זאת. נוכל לכתוב קוד אמין יותר, ממוקד וקל יותר לשימוש חוזר.
-
הודות ללמבדות, אנחנו יכולים לעשות חישובים עצלים. כאשר ביטוי למבדה נשלח כארגומנט מתודה, המהדר יעריך אותו כאשר הוא נקרא בשיטה. זה שונה מארגומנטים של שיטה רגילה, אשר מוערכים באופן מיידי.
-
למבדות הופכות מבחני יחידות כתיבה למהנים. הם מאפשרים לנו ליצור מבחנים קלים, נקיים, קטנים בגודלם ומהירים לכתיבה. אנחנו יכולים לשרש את הקוד הנבדק באמצעות lambdas. זה מאפשר לנו לבדוק כיצד כל מיני תרחישים ישפיעו על הקוד.
-
דפוסים חדשים ללמוד.
-
ועוד הרבה!
break
, לשנות באופן דרמטי את התנהגות הלולאה, מה שמאלץ אותנו להבין לא רק מה הקוד מנסה להשיג, continue
אלא return
גם להבין איך הלולאה עובדת. כעת נסקור כיצד אנו יכולים להפוך לולאות לקוד תמציתי וקריא יותר.
תן לקידוד להתחיל!
נעבוד עם מאמרים. למאמר יש כותרת, מחבר ומספר תגים.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()
, אנו מקבלים קוד נקי וקריא. עכשיו בואו נמצא את שאר התגים המשמשים באוסף. נתחיל עם דוגמה ללולאה:
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
כדי ליצור את ערכת ההחזרה.
GO TO FULL VERSION