Java 8+ features — Java’ni eski “faqat OOP” uslubidan zamonaviy, qisqa, funksional va qulay yozish uslubiga olib chiqqan imkoniyatlar.
Bu bo‘limga quyidagilar kiradi: Lambda expressions, Functional interfaces, Stream API, Optional, Method references, Default & static interface methods, Date/Time API (java.time).
1. Java 8 nega muhim?
Java 8’dan oldin ko‘p kodlar juda uzun yozilardi.
Masalan, ro‘yxatdagi ismlarni chiqarish:
List<String> names = List.of("Ali", "Vali", "Hasan");
for (String name : names) {
System.out.println(name);
}Java 8’dan keyin buni qisqaroq yozish mumkin:
names.forEach(name -> System.out.println(name));Yoki yanada qisqa:
names.forEach(System.out::println);Java 8+ sizga quyidagilarni beradi:
kamroq boilerplate kod;
collectionlar bilan qulay ishlash;
filter, map, sort, group qilish;
null bilan xavfsizroq ishlash;
vaqt/sana bilan to‘g‘ri ishlash;
funksional programming elementlari.
2. Lambda Expression
Lambda — methodni qisqa ko‘rinishda yozish usuli.
Oddiy ko‘rinishi:
(parameter) -> actionMasalan:
name -> System.out.println(name)Bu degani:
name degan qiymat keladi, uni print qilamiz2.1 Lambda oldidan qanday yozilardi?
Java 8’dan oldin anonymous class ishlatilardi.
Runnable task = new Runnable() {
@Override
public void run() {
System.out.println("Task ishladi");
}
};Java 8 bilan:
Runnable task = () -> System.out.println("Task ishladi");Bu yerda:
()— parameter yo‘q;->— lambda belgisi;System.out.println(...)— bajariladigan ish.
2.2 Lambda misollar
Bitta parameter
Consumer<String> printer = name -> System.out.println(name);
printer.accept("Ali");Ikkita parameter
BiFunction<Integer, Integer, Integer> sum = (a, b) -> a + b;
System.out.println(sum.apply(10, 20));Natija:
30Bir nechta qatorli lambda
Consumer<String> printer = name -> {
System.out.println("Name:");
System.out.println(name);
};Agar lambda ichida bir nechta qator bo‘lsa, {} ishlatiladi.
3. Functional Interface
Functional interface — ichida faqat bitta abstract method bo‘lgan interface.
Masalan:
@FunctionalInterface
public interface Calculator {
int calculate(int a, int b);
}Bu interface lambda bilan ishlatiladi:
Calculator sum = (a, b) -> a + b;
int result = sum.calculate(10, 20);
System.out.println(result);Natija:
303.1 @FunctionalInterface nima qiladi?
@FunctionalInterface
public interface Calculator {
int calculate(int a, int b);
}Bu annotation Java’ga aytadi:
Bu interface functional interface bo‘lishi kerak.
Agar ikkinchi abstract method qo‘shib yuborsangiz, compile error beradi.
@FunctionalInterface
public interface Calculator {
int calculate(int a, int b);
int minus(int a, int b); // xato
}4. Tayyor functional interfacelar
Java’da tayyor functional interfacelar bor. Eng keraklilari:
Interface | Ma’nosi | Method |
|---|---|---|
| shart tekshiradi |
|
| bir type’dan boshqa type qaytaradi |
|
| qiymat oladi, lekin qaytarmaydi |
|
| qiymat ishlab chiqaradi |
|
| bitta type olib, o‘sha type qaytaradi |
|
| ikkita bir xil type olib, bitta natija qaytaradi |
|
4.1 Predicate
Predicate — shart tekshiradi. Natija true yoki false.
Predicate<Integer> isEven = number -> number % 2 == 0;
System.out.println(isEven.test(10));
System.out.println(isEven.test(7));Natija:
true
falseReal misol:
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6);
List<Integer> evenNumbers = numbers.stream()
.filter(number -> number % 2 == 0)
.toList();
System.out.println(evenNumbers);Natija:
[2, 4, 6]4.2 Function
Function<T, R> — bitta qiymat olib, boshqa qiymat qaytaradi.
Function<String, Integer> lengthFunction = text -> text.length();
System.out.println(lengthFunction.apply("Java"));Natija:
4Real misol:
List<String> names = List.of("Ali", "Vali", "Hasan");
List<Integer> lengths = names.stream()
.map(name -> name.length())
.toList();
System.out.println(lengths);Natija:
[3, 4, 5]4.3 Consumer
Consumer<T> — qiymat oladi, lekin hech narsa qaytarmaydi.
Consumer<String> printer = text -> System.out.println(text);
printer.accept("Hello Java");Real misol:
List<String> names = List.of("Ali", "Vali", "Hasan");
names.forEach(name -> System.out.println(name));4.4 Supplier
Supplier<T> — parameter olmaydi, qiymat qaytaradi.
Supplier<Double> randomSupplier = () -> Math.random();
System.out.println(randomSupplier.get());Real misol:
Supplier<LocalDateTime> nowSupplier = () -> LocalDateTime.now();
System.out.println(nowSupplier.get());5. Stream API
Stream API — collection ichidagi ma’lumotlarni functional uslubda qayta ishlash uchun ishlatiladi.
Stream yordamida:
filter qilish;
map qilish;
sort qilish;
count qilish;
group qilish;
reduce qilish;
listga yig‘ish;
mumkin.
5.1 Oddiy stream misol
List<String> names = List.of("Ali", "Vali", "Hasan", "Aziz");
List<String> result = names.stream()
.filter(name -> name.startsWith("A"))
.toList();
System.out.println(result);Natija:
[Ali, Aziz]Bu yerda:
names.stream()collectionni streamga aylantiradi.
.filter(name -> name.startsWith("A"))faqat A bilan boshlanadiganlarni qoldiradi.
.toList()natijani listga yig‘adi.
6. Stream filter
filter — shartga mos elementlarni qoldiradi.
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6);
List<Integer> evenNumbers = numbers.stream()
.filter(number -> number % 2 == 0)
.toList();
System.out.println(evenNumbers);Natija:
[2, 4, 6]7. Stream map
map — har bir elementni boshqa ko‘rinishga o‘zgartiradi.
List<String> names = List.of("Ali", "Vali", "Hasan");
List<String> upperNames = names.stream()
.map(name -> name.toUpperCase())
.toList();
System.out.println(upperNames);Natija:
[ALI, VALI, HASAN]7.1 Entity’dan DTO yasash
Backend’da map juda ko‘p ishlatiladi.
public class User {
private Long id;
private String name;
public User(Long id, String name) {
this.id = id;
this.name = name;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
}public class UserDto {
private Long id;
private String name;
public UserDto(Long id, String name) {
this.id = id;
this.name = name;
}
}Listni DTO’ga o‘tkazish:
List<UserDto> userDtos = users.stream()
.map(user -> new UserDto(user.getId(), user.getName()))
.toList();Bu real Spring Boot loyihalarda juda ko‘p ishlatiladi.
8. Stream sorted
List<Integer> numbers = List.of(5, 1, 4, 2, 3);
List<Integer> sortedNumbers = numbers.stream()
.sorted()
.toList();
System.out.println(sortedNumbers);Natija:
[1, 2, 3, 4, 5]Objectlarni sort qilish:
List<User> sortedUsers = users.stream()
.sorted(Comparator.comparing(User::getName))
.toList();Age bo‘yicha kamayish tartibida:
List<User> sortedUsers = users.stream()
.sorted(Comparator.comparing(User::getAge).reversed())
.toList();9. Stream forEach
forEach — har bir element ustida amal bajaradi.
List<String> names = List.of("Ali", "Vali", "Hasan");
names.stream()
.forEach(name -> System.out.println(name));Yoki:
names.forEach(name -> System.out.println(name));Yanada qisqa:
names.forEach(System.out::println);Muhim: forEach odatda natija qaytarmaydi. Faqat amal bajaradi.
10. Stream count
List<String> names = List.of("Ali", "Vali", "Hasan", "Aziz");
long count = names.stream()
.filter(name -> name.startsWith("A"))
.count();
System.out.println(count);Natija:
211. Stream findFirst
List<String> names = List.of("Ali", "Vali", "Hasan");
Optional<String> first = names.stream()
.filter(name -> name.startsWith("A"))
.findFirst();
System.out.println(first.orElse("Topilmadi"));Natija:
AlifindFirst() natijasi Optional bo‘ladi. Chunki element topilmasligi ham mumkin.
12. Stream anyMatch, allMatch, noneMatch
anyMatch
Kamida bittasi mos kelsa true.
boolean hasAdult = users.stream()
.anyMatch(user -> user.getAge() >= 18);allMatch
Hammasi mos kelsa true.
boolean allAdults = users.stream()
.allMatch(user -> user.getAge() >= 18);noneMatch
Hech biri mos kelmasa true.
boolean noBlockedUsers = users.stream()
.noneMatch(user -> user.isBlocked());13. Stream reduce
reduce — collection ichidagi qiymatlarni bitta natijaga yig‘adi.
Masalan, sonlar yig‘indisi:
List<Integer> numbers = List.of(1, 2, 3, 4);
int sum = numbers.stream()
.reduce(0, (a, b) -> a + b);
System.out.println(sum);Natija:
10Qisqaroq:
int sum = numbers.stream()
.reduce(0, Integer::sum);14. Collectors
Collectors — stream natijasini yig‘ish uchun ishlatiladi.
Java 16+ da ko‘p joyda .toList() ishlatsa bo‘ladi:
List<String> result = names.stream()
.filter(name -> name.startsWith("A"))
.toList();Lekin Java 8’da odatda bunday yoziladi:
List<String> result = names.stream()
.filter(name -> name.startsWith("A"))
.collect(Collectors.toList());14.1 Setga yig‘ish
Set<String> uniqueNames = names.stream()
.collect(Collectors.toSet());14.2 Mapga yig‘ish
Map<Long, User> usersById = users.stream()
.collect(Collectors.toMap(
User::getId,
user -> user
));Bu real backend’da juda foydali.
Masalan, List<User> bor. Sizga id -> user ko‘rinishida Map kerak.
14.3 groupingBy
groupingBy — ma’lumotlarni guruhlash.
Masalan, userlarni age bo‘yicha guruhlash:
Map<Integer, List<User>> usersByAge = users.stream()
.collect(Collectors.groupingBy(User::getAge));Orderlarni status bo‘yicha guruhlash:
Map<OrderStatus, List<Order>> ordersByStatus = orders.stream()
.collect(Collectors.groupingBy(Order::getStatus));Natija taxminan:
NEW -> [order1, order2]
PAID -> [order3, order4]
CANCELLED -> [order5]15. Stream API’da muhim tushuncha
Stream operationlar ikki turga bo‘linadi:
Intermediate operations
Bular streamni qayta ishlaydi, lekin darhol ishga tushmaydi:
filtermapsorteddistinctlimitskip
Terminal operations
Bular streamni ishga tushiradi:
toListcollectforEachcountfindFirstreduceanyMatch
Misol:
List<String> result = names.stream()
.filter(name -> name.startsWith("A"))
.map(String::toUpperCase)
.toList();Bu yerda:
filter -> intermediate
map -> intermediate
toList -> terminalTerminal operation bo‘lmasa, stream ishlamaydi.
16. Method Reference
Method reference — lambda’ni yanada qisqa yozish usuli.
Lambda:
names.forEach(name -> System.out.println(name));Method reference:
names.forEach(System.out::println);16.1 Method reference turlari
Static method reference
Function<String, Integer> parser = Integer::parseInt;Bu shunga teng:
Function<String, Integer> parser = text -> Integer.parseInt(text);Instance method reference
List<String> upperNames = names.stream()
.map(String::toUpperCase)
.toList();Bu shunga teng:
.map(name -> name.toUpperCase())Constructor reference
Supplier<ArrayList<String>> listSupplier = ArrayList::new;Bu shunga teng:
Supplier<ArrayList<String>> listSupplier = () -> new ArrayList<>();17. Optional
Optional — qiymat bor yoki yo‘qligini xavfsiz ifodalash uchun ishlatiladi.
U null o‘rnini to‘liq bosmaydi, lekin method natijasida “topilishi ham, topilmasligi ham mumkin” degan holatni aniq ko‘rsatadi.
17.1 Optional yaratish
Optional<String> name = Optional.of("Ali");Bo‘sh Optional:
Optional<String> empty = Optional.empty();Null bo‘lishi mumkin bo‘lgan qiymatdan:
String text = getName();
Optional<String> optionalText = Optional.ofNullable(text);ofNullable null kelsa xato bermaydi, Optional.empty() qiladi.
17.2 Optional ishlatish
Yomon usul:
User user = userRepository.findById(1L);
if (user != null) {
System.out.println(user.getName());
}Yaxshi usul:
Optional<User> optionalUser = userRepository.findById(1L);
optionalUser.ifPresent(user -> System.out.println(user.getName()));17.3 orElse
String name = optionalName.orElse("Noma'lum");Agar qiymat bo‘lsa — o‘sha qiymat. Bo‘lmasa — "Noma'lum".
17.4 orElseThrow
Spring Boot’da juda ko‘p ishlatiladi:
User user = userRepository.findById(id)
.orElseThrow(() -> new RuntimeException("User topilmadi"));Bu degani:
User topilsa qaytar. Topilmasa exception ot.
17.5 Optional bilan map
Optional<String> userName = userRepository.findById(id)
.map(User::getName);Agar user topilsa, uning name’ini oladi. Topilmasa, empty qoladi.
17.6 Optional xatolari
Yomon:
Optional<User> user = userRepository.findById(id);
if (user.isPresent()) {
System.out.println(user.get().getName());
}Bu ishlaydi, lekin ko‘pincha chiroyli emas.
Yaxshiroq:
userRepository.findById(id)
.ifPresent(user -> System.out.println(user.getName()));Yoki kerak bo‘lsa:
User user = userRepository.findById(id)
.orElseThrow(() -> new RuntimeException("User topilmadi"));18. Default methods in interface
Java 8’dan boshlab interface ichida tayyor method yozish mumkin.
public interface PaymentService {
void pay(double amount);
default void printInfo() {
System.out.println("Payment service");
}
}Implementation class printInfo()ni yozmasa ham bo‘ladi.
public class ClickPaymentService implements PaymentService {
@Override
public void pay(double amount) {
System.out.println("Click orqali to'landi");
}
}Ishlatish:
PaymentService service = new ClickPaymentService();
service.pay(100_000);
service.printInfo();18.1 Nega default method kerak?
Asosiy sabab:
Eski interface’ga yangi method qo‘shilganda, eski implementation classlar buzilib ketmasin.
Masalan, sizda interface bor:
public interface ReportService {
void generate();
}Keyin unga yangi method qo‘shmoqchisiz:
public interface ReportService {
void generate();
default void exportPdf() {
System.out.println("PDF export qilindi");
}
}Endi eski classlar exportPdf()ni majburiy override qilishi shart emas.
19. Static methods in interface
Interface ichida static method ham yozish mumkin.
public interface MathUtils {
static int square(int number) {
return number * number;
}
}Ishlatish:
int result = MathUtils.square(5);
System.out.println(result);Natija:
25Static interface method obyekt orqali emas, interface nomi orqali chaqiriladi.
20. Date/Time API — java.time
Java 8’dan oldin Date va Calendar ishlatilardi. Ular noqulay va xatoga moyil edi.
Java 8’da yangi java.time API keldi.
Eng kerakli classlar:
Class | Ma’nosi |
|---|---|
| faqat sana |
| faqat vaqt |
| sana + vaqt |
| timezone bilan sana/vaqt |
| aniq vaqt nuqtasi |
| vaqt oralig‘i |
| sana oralig‘i |
20.1 LocalDate
LocalDate today = LocalDate.now();
System.out.println(today);Natija:
2026-05-20Sana yaratish:
LocalDate birthDate = LocalDate.of(2000, 5, 10);20.2 LocalTime
LocalTime now = LocalTime.now();
System.out.println(now);20.3 LocalDateTime
LocalDateTime now = LocalDateTime.now();
System.out.println(now);Bu sana va vaqtni beradi, lekin timezone saqlamaydi.
20.4 Sana qo‘shish/ayirish
LocalDate today = LocalDate.now();
LocalDate tomorrow = today.plusDays(1);
LocalDate nextMonth = today.plusMonths(1);
LocalDate yesterday = today.minusDays(1);20.5 DateTimeFormatter
LocalDate date = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
String formatted = date.format(formatter);
System.out.println(formatted);Natija:
20.05.2026Stringdan date yasash:
String text = "20.05.2026";
LocalDate date = LocalDate.parse(
text,
DateTimeFormatter.ofPattern("dd.MM.yyyy")
);21. Real backend misol: Order filter
Tasavvur qiling, orderlar ro‘yxati bor.
public class Order {
private Long id;
private String customerName;
private OrderStatus status;
private int amount;
private LocalDateTime createdAt;
public Order(Long id, String customerName, OrderStatus status, int amount, LocalDateTime createdAt) {
this.id = id;
this.customerName = customerName;
this.status = status;
this.amount = amount;
this.createdAt = createdAt;
}
public Long getId() {
return id;
}
public String getCustomerName() {
return customerName;
}
public OrderStatus getStatus() {
return status;
}
public int getAmount() {
return amount;
}
public LocalDateTime getCreatedAt() {
return createdAt;
}
}Status enum:
public enum OrderStatus {
NEW,
PAID,
CANCELLED
}Orderlarni filter qilish:
List<Order> paidOrders = orders.stream()
.filter(order -> order.getStatus() == OrderStatus.PAID)
.toList();Summani hisoblash:
int totalAmount = orders.stream()
.filter(order -> order.getStatus() == OrderStatus.PAID)
.mapToInt(Order::getAmount)
.sum();Eng oxirgi orderni topish:
Optional<Order> latestOrder = orders.stream()
.max(Comparator.comparing(Order::getCreatedAt));Status bo‘yicha guruhlash:
Map<OrderStatus, List<Order>> ordersByStatus = orders.stream()
.collect(Collectors.groupingBy(Order::getStatus));22. Stream API’da ehtiyot bo‘lish kerak bo‘lgan joylar
22.1 Juda murakkab stream yozish
Yomon:
List<String> result = users.stream()
.filter(u -> u.getAge() > 18)
.filter(u -> !u.isBlocked())
.map(u -> u.getOrders())
.flatMap(o -> o.stream())
.filter(o -> o.getAmount() > 100000)
.map(o -> o.getProduct().getName())
.distinct()
.sorted()
.toList();Bu ishlaydi, lekin o‘qish qiyin.
Bunday holatda oddiy methodlarga ajratgan yaxshi.
22.2 Stream ichida side effect qilish
Yomon:
List<String> result = new ArrayList<>();
users.stream()
.filter(user -> user.getAge() > 18)
.forEach(user -> result.add(user.getName()));Yaxshi:
List<String> result = users.stream()
.filter(user -> user.getAge() > 18)
.map(User::getName)
.toList();22.3 Null qiymatlar
Agar list ichida null bo‘lsa:
List<String> names = Arrays.asList("Ali", null, "Vali");
List<String> upperNames = names.stream()
.map(String::toUpperCase)
.toList();Bu NullPointerException beradi.
Yaxshi:
List<String> upperNames = names.stream()
.filter(Objects::nonNull)
.map(String::toUpperCase)
.toList();23. Java 8+ features qayerda ko‘p ishlatiladi?
Spring Boot backend’da:
userRepository.findById(id)
.orElseThrow(() -> new RuntimeException("User topilmadi"));List<UserDto> users = userRepository.findAll().stream()
.map(userMapper::toDto)
.toList();Map<Long, Product> productsById = products.stream()
.collect(Collectors.toMap(Product::getId, product -> product));orders.stream()
.filter(order -> order.getStatus() == OrderStatus.PAID)
.mapToInt(Order::getAmount)
.sum();24. Junior uchun eng muhim qismlar
Mavzu | Bilish darajasi |
|---|---|
Lambda | Majburiy |
Functional interface | Majburiy |
| Kerak |
Stream | Majburiy |
Stream | Kerak |
| Kerak |
Optional | Majburiy |
Method reference | Kerak |
| Majburiy |
Default/static interface methods | Asosiy tushuncha yetadi |
25. Amaliy mashq
Vazifa: User filter system
User class yarating:
public class User {
private Long id;
private String name;
private int age;
private boolean active;
public User(Long id, String name, int age, boolean active) {
this.id = id;
this.name = name;
this.age = age;
this.active = active;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public boolean isActive() {
return active;
}
}List yarating:
List<User> users = List.of(
new User(1L, "Ali", 25, true),
new User(2L, "Vali", 17, true),
new User(3L, "Hasan", 30, false),
new User(4L, "Aziz", 22, true)
);Quyidagilarni bajaring:
Faqat active userlarni oling.
Faqat 18 yoshdan kattalarni oling.
User name’larini
List<String>qilib oling.Userlarni age bo‘yicha sort qiling.
Map<Long, User>yasang.Active userlar sonini hisoblang.
Eng katta yoshli userni toping.
Optional<User>orqaliid = 10bo‘lgan userni qidiring.Topilmasa
"User topilmadi"exception chiqaring.Bugungi sanani
dd.MM.yyyyformatda chiqaring.
Xulosa
Java 8+ features Junior Java developer uchun juda muhim.
Asosiy eslab qoling:
list.stream()
.filter(...)
.map(...)
.toList();Optional<User> user = repository.findById(id);users.forEach(System.out::println);LocalDate.now();
LocalDateTime.now();Java 8+ sizga kodni:
qisqaroq;
o‘qilishi osonroq;
xavfsizroq;
functional uslubga yaqinroq;
backend API uchun qulayroq
qilib yozishga yordam beradi.