-
يساعدنا النمط الوظيفي المقدم في Java 8 على تقليل الفجوة بين منطق الأعمال والتعليمات البرمجية. إنها تتيح لنا رواية القصة بتدفق طبيعي على مستوى أعلى. بدلاً من أن تقول كيف تريد أن تفعل ذلك، يمكنك أن تقول ما تريد أن تفعله.
-
يصبح الكود أنظف وأكثر إيجازًا.
-
وظائف الترتيب العالي تسمح لنا بما يلي:
- إرسال الوظائف إلى وظائف أخرى
- إنشاء وظائف داخل وظائف أخرى
- إرجاع الوظائف من وظائف أخرى
يعد هذا فوزًا كبيرًا لـ Java، حيث نحتاج إلى إرسال الكائنات وإنشائها وإعادتها للقيام بذلك. سنكون قادرين على كتابة تعليمات برمجية أكثر موثوقية وتركيزًا وأسهل في إعادة الاستخدام.
-
بفضل لامدا، يمكننا إجراء حسابات كسولة. عندما يتم إرسال تعبير لامدا كوسيطة أسلوب، سيقوم المترجم بتقييمه عند استدعائه في الأسلوب. وهذا يختلف عن وسيطات الطريقة العادية، والتي يتم تقييمها على الفور.
-
Lambdas تجعل اختبارات وحدة الكتابة ممتعة. إنها تتيح لنا إنشاء اختبارات خفيفة الوزن ونظيفة وصغيرة الحجم وسريعة الكتابة. يمكننا استئصال الكود قيد الاختبار باستخدام 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