Java Streams API
Streams Nədir?
Java Streams API (Java 8) kolleksiyalar üzərində funksional əməliyyatlar aparmaq üçün güclü vasitədir. Data-nın emalını deklarativ üslubda həyata keçirir.
Stream Xüsusiyyətləri
- Deklarativ - Nəyin ediləcəyini təyin edir
- Funksional - Funksional proqramlaşdırma prinsipləri
- Lazy Evaluation - Lazım olduqda hesablama
- Pipeline - Əməliyyatların zənciri
- Parallelizm - Parallel emal imkanı
Stream Yaratmaq
// Kolleksiyadan
List<String> list = Arrays.asList("A", "B", "C");
Stream<String> stream1 = list.stream();
// Array-dən
String[] array = {"X", "Y", "Z"};
Stream<String> stream2 = Arrays.stream(array);
// Stream.of()
Stream<Integer> stream3 = Stream.of(1, 2, 3, 4, 5);
// Stream.generate()
Stream<Double> stream4 = Stream.generate(Math::random).limit(5);
// Stream.iterate()
Stream<Integer> stream5 = Stream.iterate(0, n -> n + 2).limit(10);
Intermediate Əməliyyatlar
filter()
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> evens = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
// [2, 4, 6, 8, 10]
map()
List<String> words = Arrays.asList("java", "python", "javascript");
List<String> upperCase = words.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
// [JAVA, PYTHON, JAVASCRIPT]
flatMap()
List<List<String>> nested = Arrays.asList(
Arrays.asList("A", "B"),
Arrays.asList("C", "D")
);
List<String> flattened = nested.stream()
.flatMap(Collection::stream)
.collect(Collectors.toList());
// [A, B, C, D]
distinct()
List<Integer> duplicates = Arrays.asList(1, 2, 2, 3, 3, 4);
List<Integer> unique = duplicates.stream()
.distinct()
.collect(Collectors.toList());
// [1, 2, 3, 4]
sorted()
List<String> names = Arrays.asList("John", "Alice", "Bob");
List<String> sorted = names.stream()
.sorted()
.collect(Collectors.toList());
// [Alice, Bob, John]
// Custom comparator
List<String> byLength = names.stream()
.sorted(Comparator.comparing(String::length))
.collect(Collectors.toList());
limit() və skip()
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> firstFive = numbers.stream()
.limit(5)
.collect(Collectors.toList());
// [1, 2, 3, 4, 5]
List<Integer> skipFirst = numbers.stream()
.skip(5)
.collect(Collectors.toList());
// [6, 7, 8, 9, 10]
Terminal Əməliyyatlar
collect()
List<String> names = Arrays.asList("Ali", "Vəli", "Ayşə");
// toList()
List<String> list = names.stream().collect(Collectors.toList());
// toSet()
Set<String> set = names.stream().collect(Collectors.toSet());
// joining()
String joined = names.stream().collect(Collectors.joining(", "));
// "Ali, Vəli, Ayşə"
// groupingBy()
Map<Integer, List<String>> byLength = names.stream()
.collect(Collectors.groupingBy(String::length));
forEach()
List<String> names = Arrays.asList("Ali", "Vəli", "Ayşə");
names.stream()
.filter(name -> name.length() > 3)
.forEach(System.out::println);
reduce()
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// Sum
int sum = numbers.stream()
.reduce(0, Integer::sum);
// 15
// Max
Optional<Integer> max = numbers.stream()
.reduce(Integer::max);
// Optional[5]
// String concatenation
List<String> words = Arrays.asList("Java", "is", "awesome");
String sentence = words.stream()
.reduce("", (a, b) -> a + " " + b).trim();
// "Java is awesome"
Matching əməliyyatları
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean allEven = numbers.stream().allMatch(n -> n % 2 == 0); // false
boolean anyEven = numbers.stream().anyMatch(n -> n % 2 == 0); // true
boolean noneNegative = numbers.stream().noneMatch(n -> n < 0); // true
find əməliyyatları
List<String> names = Arrays.asList("Ali", "Vəli", "Ayşə");
Optional<String> first = names.stream()
.filter(name -> name.startsWith("A"))
.findFirst();
Optional<String> any = names.stream()
.filter(name -> name.length() > 3)
.findAny();
Primitive Streams
// IntStream
IntStream intStream = IntStream.range(1, 6); // 1, 2, 3, 4, 5
int sum = intStream.sum(); // 15
// Statistics
IntSummaryStatistics stats = IntStream.range(1, 101)
.summaryStatistics();
System.out.println("Average: " + stats.getAverage());
System.out.println("Max: " + stats.getMax());
// DoubleStream
DoubleStream doubleStream = DoubleStream.of(1.1, 2.2, 3.3);
double average = doubleStream.average().orElse(0.0);
Parallel Streams
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// Sequential
int sum1 = numbers.stream()
.mapToInt(Integer::intValue)
.sum();
// Parallel
int sum2 = numbers.parallelStream()
.mapToInt(Integer::intValue)
.sum();
// Custom parallel
int sum3 = numbers.stream()
.parallel()
.mapToInt(Integer::intValue)
.sum();
Praktik Nümunələr
Employee filtrasiyası
class Employee {
String name;
int salary;
String department;
// constructors, getters
}
List<Employee> employees = getEmployees();
// Yüksək maaşlı IT işçiləri
List<Employee> highPaidIT = employees.stream()
.filter(e -> "IT".equals(e.getDepartment()))
.filter(e -> e.getSalary() > 50000)
.collect(Collectors.toList());
// Departmentə görə orta maaş
Map<String, Double> avgSalaryByDept = employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.averagingInt(Employee::getSalary)
));
File Processing
try (Stream<String> lines = Files.lines(Paths.get("file.txt"))) {
long wordCount = lines
.flatMap(line -> Arrays.stream(line.split("\\s+")))
.map(String::toLowerCase)
.distinct()
.count();
}
Best Practices
-
Terminal əməliyyat mütləqdir:
stream.filter(x -> x > 0); // ❌ Heç nə etmir
stream.filter(x -> x > 0).collect(Collectors.toList()); // ✅ -
Stream yalnız bir dəfə istifadə olunur:
Stream<String> stream = list.stream();
stream.forEach(System.out::println); // ✅
stream.count(); // ❌ IllegalStateException -
Parallel stream böyük data üçün:
// Kiçik kolleksiya üçün sequential daha yaxşıdır
if (list.size() > 1000) {
list.parallelStream()...
} else {
list.stream()...
} -
Method reference istifadə edin:
.map(s -> s.length()) // ❌
.map(String::length) // ✅