import java.util.*;
import java.util.stream.*;

public class StreamOperations {
    
    // Filter elements
    public static <T> List<T> filter(List<T> list, Predicate<T> predicate) {
        return list.stream()
            .filter(predicate)
            .collect(Collectors.toList());
    }
    
    // Map elements to another type
    public static <T, R> List<R> map(List<T> list, Function<T, R> mapper) {
        return list.stream()
            .map(mapper)
            .collect(Collectors.toList());
    }
    
    // Reduce to single value
    public static <T> Optional<T> reduce(List<T> list, BinaryOperator<T> accumulator) {
        return list.stream().reduce(accumulator);
    }
    
    // Group by classifier
    public static <T, K> Map<K, List<T>> groupBy(List<T> list, Function<T, K> classifier) {
        return list.stream()
            .collect(Collectors.groupingBy(classifier));
    }
    
    // Flat map nested collections
    public static <T, R> List<R> flatMap(List<List<T>> nested, Function<List<T>, Stream<R>> mapper) {
        return nested.stream()
            .flatMap(mapper)
            .collect(Collectors.toList());
    }
    
    // Distinct elements
    public static <T> List<T> distinct(List<T> list) {
        return list.stream()
            .distinct()
            .collect(Collectors.toList());
    }
    
    // Sort elements
    public static <T> List<T> sorted(List<T> list, Comparator<T> comparator) {
        return list.stream()
            .sorted(comparator)
            .collect(Collectors.toList());
    }
}