class NumberMultiplier {
public long multipleByTwo(int number) {
final int result = number * 2;
return result;
}
}
class Counter {
private long count;
public long increment() {
return ++count;
}
public long getCount() {
return count;
}
}
class Counter {
private long count;
public long increment() {
int temp = count;
temp = temp + 1;
count = temp;
return count;
}
public long getCount() {
return count;
}
}
class AtomicCounter {
private AtomicLong count;
public long increment() {
return count.incrementAndGet();
}
public long getCount() {
return count.get();
}
}
public class Incrementer {
private AtomicLong value;
private AtomicLong latestDelta;
public void increment(long delta) {
value.addAndGet(delta);
latestDelta.set(delta);
}
}
synchronized (lock) {
// код
}
// Thread 1: doSomething(new Object());
// Thread 2: doSomething(new Object());
public void doSomething(Object lock) {
synchronized (lock) {
// ...
}
}
public void increment(long delta) {
synchronized (this) {
count.addAndGet(delta);
latestIncrement.set(delta);
}
}
public synchronized void increment(long delta) {
count.addAndGet(delta);
latestIncrement.set(delta);
}
public class Incrementer {
private long value;
private long latestDelta;
public synchronized void increment(long delta) {
value += delta;
latestDelta = delta;
}
}
volatile int sharedVar = 3;
private volatile int sharedVar = 3;
public void updateSharedVar(){
sharedVar += 3;
}
private volatile int sharedVar = 3;
thread 1: sharedVar += 3;
// thread 1 reads 3
thread 2: sharedVar += 3;
// thread 2 reads 3
// thread 1 increments, writes 6
// thread 2 increments, writes 6
// sharedVar = 6, not 9
private volatile int sharedVar = 3;
public void updateSharedVar(int value){
sharedVar = value;
}
private int sharedVar = 3;
public synchronized void updateShareVar(){
sharedVar += 3;
}
private final int constant = 42;
class PrimeGenerator implements Runnable {
private final List<BigInteger> primes = new CopyOnWriteArrayList<BigInteger>();
@Override
public void run() {
BigInteger p = BigInteger.ONE;
while (true) {
p = p.nextProbablePrime();
primes.add(p);
}
}
public List<BigInteger> getPrimes() {
return primes;
}
}
...
PrimeGenerator primeGenerator = new PrimeGenerator();
Thread t = new Thread(primeGenerator);
t.start();
class PrimeGenerator implements Runnable {
private final List<BigInteger> primes = new CopyOnWriteArrayList<BigInteger>();
@Override
public void run() {
BigInteger p = BigInteger.ONE;
while (!Thread.currentThread().isInterrupted()) {
p = p.nextProbablePrime();
primes.add(p);
}
}
public List<BigInteger> getPrimes() {
return primes;
}
}
...
PrimeGenerator primeGenerator = new PrimeGenerator();
Thread t = new Thread(primeGenerator);
t.start();
// do some logic
t.interrupt();
class PrimeGenerator implements Runnable {
private final BlockingQueue<BigInteger> primes;
public PrimeGenerator(BlockingQueue<BigInteger> primes) {
this.primes = primes;
}
@Override
public void run() {
BigInteger p = BigInteger.ONE;
try {
while (!Thread.currentThread().isInterrupted()) {
p = p.nextProbablePrime();
primes.put(p);
}
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
...
PrimeGenerator primeGenerator = new PrimeGenerator(someBlockingQueue);
Thread t = new Thread(primeGenerator);
t.start();
// do some logic
t.interrupt();
SynchronizedCollection(Collection<E> c) {
this.c = Objects.requireNonNull(c);
mutex = this;
}
public boolean add(E e) {
synchronized (mutex) {return c.add(e);}
}
public boolean remove(Object o) {
synchronized (mutex) {return c.remove(o);}
}
public boolean containsAll(Collection<?> coll) {
synchronized (mutex) {return c.containsAll(coll);}
}
public boolean addAll(Collection<? extends E> coll) {
synchronized (mutex) {return c.addAll(coll);}
}
List<Integer> synchronizedList = Collections.synchronizedList(new ArrayList<>());
synchronizedList.addAll(List.of(1, 2, 3, 4, 5));
synchronized (synchronizedList) {
for (Integer element : synchronizedList) {
//some logic
}
}
class Book {
private String author;
private String title;
private String genre;
private Integer pageCount;
// конструктор, геттеры, сеттеры
}
List<Book> books = List.of(
new Book("Пушкин", "Евгений Онегин", "Роман", 352),
new Book("Лермонтов", "Герой нашего времени", "Роман", 224),
new Book("Гоголь", "Мёртвые души", "Поэма", 560),
new Book("Гоголь", "Шинель", "Повесть", 64));
Map<String, List<Book>> byGenre = books.stream()
.collect(groupingBy(Book::getGenre));
// byGenre = {Поэма=['Мёртвые души'], Роман=['Евгений Онегин', 'Герой нашего времени'], Повесть=['Шинель']}
summingInt()
summingLong()
summingDouble()
Map<String, Integer> totalLengthByGenre = books.stream()
.collect(groupingBy(Book::getGenre,
summingInt(Book::getPageCount)));
// totalLengthByGenre = {Поэма=560, Роман=576, Повесть=64}
Map<String, Double> averageLength = books.stream()
.collect(groupingBy(Book::getGenre,
averagingInt(Book::getPageCount)));
System.out.println("averageLength: " + averageLength);
// averageLength: {Поэма=560.0, Роман=288.0, Повесть=64.0}
Map<String, IntSummaryStatistics> statisticsByGenre = books.stream()
.collect(groupingBy(Book::getGenre,
summarizingInt(Book::getPageCount)));
/*
statisticsByGenre = {
Поэма=IntSummaryStatistics{
count=1, sum=560, min=560, average=560.000000, max=560},
Роман=IntSummaryStatistics{
count=2, sum=576, min=224, average=288.000000, max=352},
Повесть=IntSummaryStatistics{
count=1, sum=64, min=64, average=64.000000, max=64}
}
*/
Map<String, Optional<Book>> maxLengthByAuthor = books.stream()
.collect(groupingBy(Book::getAuthor,
maxBy(Comparator.comparingInt(Book::getPageCount))));
// maxLengthByAuthor = {Пушкин=Optional['Евгений Онегин'], Гоголь=Optional['Мёртвые души'], Лермонтов=Optional['Герой нашего времени']}
Map<String, Set<String>> genresByAuthor = books.stream()
.collect(groupingBy(Book::getAuthor,
mapping(Book::getGenre, toSet())));
// genresByAuthor = {Пушкин=[Роман], Гоголь=[Поэма, Повесть], Лермонтов=[Роман]}
Map<String, Set<Book>> shortBooks = books.stream()
.collect(groupingBy(Book::getAuthor,
filtering(b -> b.getPageCount() < 100,
toSet())));
// shortBooks = {Пушкин=[], Гоголь=['Шинель'], Лермонтов=[]}
// shortBooks = {Гоголь=['Шинель']}
class Book {
...
private List<String> comments = new ArrayList<>();
...
onegin.setComments(List.of("Отлично!", "Хорошо"));
shinel.setComments(List.of("Нормально", "Хорошо", "Отлично!"));
Map<String, List<List<String>>> collect = books.stream()
.collect(groupingBy(Book::getAuthor,
mapping(Book::getComments,
toList())));
Map<String, List<String>> authorComments = books.stream()
.collect(groupingBy(Book::getAuthor,
flatMapping(book -> book.getComments().stream(),
toList())));
// authorComments = {Пушкин=[Отлично!, Хорошо], Гоголь=[Нормально, Хорошо, Отлично!], Лермонтов=[]}
() -> new MutableInteger(0)
class MutableInteger {
private int value;
public MutableInteger(int value) {
this.value = value;
}
public void add(int value) {
this.value += value;
}
public int getValue() {
return this.value;
}
}
(accumulator, article) -> accumulator.add(article.getWordCount())
(left, right) -> {
left.add(right.getValue());
return left;
}
Collector<Article, Integer, Integer> collector = Collector.of(
() -> new MutableInteger(0),
(accumulator, article) -> accumulator.add(article.getWordCount()),
(left, right) -> {
left.add(right.getValue());
return left;
}
);
Collector<Article, Integer, Integer> collector = Collector.of(
() -> new MutableInteger(0),
(accumulator, article) -> accumulator.add(article.getWordCount()),
(left, right) -> {
left.add(right.getValue());
return left;
},
accumulator -> accumulator.getValue()
);
Collector.of(
// supplier,
// accumulator,
// combiner,
// finisher,
Collector.Characteristics.CONCURRENT,
Collector.Characteristics.IDENTITY_FINISH,
// ...
);
class SubscriptionService {
private final TransactionTemplate transaction;
public void buySubscription(User user) {
transaction.execute(() -> {
user.checkSubscriptionStatus();
user.applySubscription();
});
}
}
class SubscriptionService {
private final TransactionTemplate transaction;
private final AuditService auditService;
public void buySubscription(User user) {
transaction.execute(() -> {
user.checkSubscriptionStatus();
user.applySubscription();
});
auditService.notifyAboutBoughSubscription(user);
}
}
class SubscriptionService {
private final TransactionTemplate transaction;
private final BlockingQueue<SubscribtionBoughtEvent> queue;
public void buySubscription(User user) throws InterruptedException {
transaction.execute(() -> {
user.checkSubscriptionStatus();
user.applySubscription();
});
queue.put(new SubscribtionBoughtEvent(user));
}
}
class SubscriptionBoughtEventListener {
private final BlockingQueue<SubscribtionBoughtEvent> queue;
private final AuditService auditService;
public void notifyAboutBoughtSubscription() throws InterruptedException {
while (true) {
SubscribtionBoughtEvent event = queue.take();
auditService.notifyAboutBoughSubscription(event);
}
}
}
List<String> strings = List.of("a", "b", "c");
Stream<String> stream = strings.stream();
// сгенерирует 10 приветствий Марку
Stream.generate(() -> "Hi, Mark!")
.limit(10);
// сгенерирует 3 случайных числа с плавающей точкой
Stream.generate(new Random()::nextFloat)
.limit(3);
IntStream.range(0, 3); // 0, 1, 2
LongStream.rangeClosed(0L, 3L); // 0L, 1L, 2L, 3L
Stream<Integer> builtStream = Stream.<Integer>builder()
.add(1)
.add(2)
.add(3)
.build();
Stream<Object> builtStream = Stream.builder()
.add(1)
.add("hi")
.add(List.of(1, 2, 3))
.build();
Set<String> pizzaIngredients = Set.of("tomato", "flour", "water", "cheese");
pizzaIngredients.stream()
.filter(ingredient -> ingredient.contains("e"));
// water, cheese
Set<String> pizzaIngredients = Set.of("tomato", "flour", "water", "cheese");
pizzaIngredients.stream()
.sorted()
.forEach(System.out::println);
// cheese, flour, tomato, water
Stream.of(2, 3, 1, 0)
.sorted()
.forEach(System.out::println);
// 0, 1, 2, 3
public static int compare(int x, int y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
public class Pizza implements Comparable<Pizza> {
private String name;
private List<String> ingredients;
//other methods
}
@Override
public int compareTo(Pizza otherPizza) {
return hasPineapple(this) == hasPineapple(otherPizza) ? 0
: (hasPineapple(this) ? 1 : -1);
}
private boolean hasPineapple(Pizza pizza) {
return pizza.ingredients.contains("pineapple");
}
Pizza margarita = new Pizza("Margarita", List.of("tomato", "flour", "water", "cheese"));
Pizza hawaiian = new Pizza("Hawaiian", List.of("tomato", "flour", "water", "cheese", "pineapple"));
Stream.of(margarita, hawaiian)
.sorted();
// Margarita, Hawaiian
IntStream.rangeClosed(0, 3)
.map(e -> e * 2); // 0, 2, 4, 6
IntStream.range(0, 4)
.reduce((el, acc) -> el + acc); // 6
Set<Integer> integerSet = Stream.of(1, 2, 3, 4, 5, 4, 3, 2, 1)
.collect(Collectors.toSet()); // [1, 2, 3, 4, 5]
Map<Integer, Integer> integerMap = Stream.of(1, 1, 1, 2, 3, 3, 3, 3, 3)
.collect(Collectors.toMap(e -> e, e -> 1, Integer::sum));
// {1=3, 2=1, 3=5}
Set.of("tomato", "flour", "water", "cheese", "pineapple")
.stream()
.filter(e -> {
System.out.println("I did something");
return e.contains("e");
});
Set.of("tomato", "flour", "water", "cheese", "pineapple")
.stream()
.filter(e -> {
System.out.println("I did something");
return e.contains("e");
})
.collect(Collectors.toList());
Set.of("tomato", "flour", "water", "cheese", "pineapple")
.stream()
.filter(e -> {
System.out.println("I did something");
return e.contains("e");
})
.filter(e -> {
System.out.println("I did something too");
return e.startsWith("p");
})
.collect(Collectors.toList());
Stream.of(1, 2, 3)
.parallel()
.map(e -> e * 2)
.forEach(System.out::println); // 2, 6, 4
List.of(1, 2, 3)
.parallelStream()
.map(e -> e * 2)
.forEach(System.out::println); // 6, 4, 2
List.of(1, 2, 3)
.parallelStream()
.map(e -> e * 2)
.sequential()
.forEach(System.out::println); //2, 4, 6
public final S parallel() {
sourceStage.parallel = true;
return (S) this;
}
public final S sequential() {
sourceStage.parallel = false;
return (S) this;
}
ForkJoinPool pool = new ForkJoinPool(3);
List<Integer> list = List.of(1, 2, 3);
pool.submit(() -> list.parallelStream()
.map(e -> e * 2)
.forEach(System.out::println)
).get();
pool.shutdown();
class WebServer {
public static void main(String[] args) throws IOException {
ServerSocket socket = new ServerSocket(80);
while (true) {
Socket connection = socket.accept();
handleRequest(connection);
}
}
}
class WebServer {
public static void main(String[] args) throws IOException {
ServerSocket socket = new ServerSocket(80);
while (true) {
Socket connection = socket.accept();
new Thread(() -> handleRequest(connection)).start();
}
}
}
Future<Response> future = executorService.submit(() -> sendRequestToRemoteServer());
Future<Response> future = executorService.submit(() -> sendRequestToRemoteServer());
...
Response response = future.get();
Future<Response> future = executorService.submit(() -> sendRequestToRemoteServer());
...
Response response = future.get(3, TimeUnit.SECONDS);
// Какая-то долгая и сложная задача, которая возвращает Future<Integer>
Future<Integer> future = new Counter.countSomethingBig();
while(!future.isDone()) {
System.out.println("Counting...");
Thread.sleep(300);
}
Integer result = future.get();
CompletableFuture<String> completableFuture = CompletableFuture
.supplyAsync(() -> GroundControl.getStatus());
CompletableFuture<Void> completableFuture = CompletableFuture
.runAsync(() -> MajorTom.sendStatus());
Executor executor = Executors.newCachedThreadPool();
CompletableFuture<Void> completableFuture = CompletableFuture
.runAsync(() -> MajorTom.sendStatus(), executor);
CompletableFuture<String> completableFuture = new CompletableFuture<>();
try {
//заблокирует главный поток на 100 миллисекунд
completableFuture.get(100, TimeUnit.MILLISECONDS);
} catch (Exception e){
logger.warn("Completing future with default value", e);
} finally {
completableFuture.complete("Устал ждать");
}
CompletableFuture<String> createBalanceInfo = CompletableFuture.supplyAsync(() -> {
long amountOfMoney = Counter.countMoney();
return amountOfMoney;
}).thenApply(amountOfMoney -> {
return "There is a lot of money:" + amountOfMoney;
});
logger.info(createBalanceInfo.get());
CompletableFuture<Void> createBalanceInfo = CompletableFuture.supplyAsync(() -> {
long amountOfMoney = Counter.countMoney();
return amountOfMoney;
}).thenAccept(amountOfMoney -> send(amountOfMoney));
CompletableFuture<Void> createBalanceInfo = CompletableFuture.supplyAsync(() -> {
long amountOfMoney = Counter.countMoney();
return amountOfMoney;
}).thenRun(() -> logger.info("Created balance info"));
public <U> CompletableFuture<U> thenApply(
Function<? super T,? extends U> fn) {
return uniApplyStage(null, fn);
}
public <U> CompletableFuture<U> thenApplyAsync(
Function<? super T,? extends U> fn) {
return uniApplyStage(defaultExecutor(), fn);
}
public <U> CompletableFuture<U> thenApplyAsync(
Function<? super T,? extends U> fn, Executor executor) {
return uniApplyStage(screenExecutor(executor), fn);
}
CompletableFuture<String> createBalanceInfo = CompletableFuture.supplyAsync(() -> {
long amountOfMoney = Counter.countMoney();
return amountOfMoney;
}).thenApplyAsync(amountOfMoney -> {
return "There is a lot of money:" + amountOfMoney;
});
logger.info(createBalanceInfo.get());
Executor executor = Executors.newFixedThreadPool(2);
CompletableFuture<String> createBalanceInfo = CompletableFuture.supplyAsync(() -> {
long amountOfMoney = Counter.countMoney();
return amountOfMoney;
}).thenApplyAsync(amountOfMoney -> {
return "There is a lot of money:" + amountOfMoney;
}, executor);
CompletableFuture<ClientInfo> getClientInfo(String clientId) {
return CompletableFuture.supplyAsync(() -> ClientService.getClientInfo(clientId));
}
CompletableFuture<BalanceInfo> getBalanceInfo (ClientInfo clientInfo){
return CompletableFuture.supplyAsync(() -> {
int balanceId = clientInfo.getBalanceId();
return BalanceService.getBalanceInfo(balanceId);
});
}
CompletableFuture<BalanceInfo> balanceInfo = getClientInfo(clientId)
.thenCompose(clientInfo -> getBalanceInfo(clientInfo));
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> "Ground Control to ")
.thenCombine(CompletableFuture.supplyAsync(() -> "Major Tom"), String::concat);
CompletableFuture<String> future1 = CompletableFuture
.supplyAsync(() -> "Ground Control to");
CompletableFuture<String> future2 = CompletableFuture
.supplyAsync(() -> "Major Tom");
CompletableFuture<String> future3 = CompletableFuture
.supplyAsync(() -> "Take your protein pills and put your helmet on");
CompletableFuture<Void> completableFuture = CompletableFuture.allOf(future1, future2, future3);
String combined = Stream.of(future1, future2, future3)
.map(CompletableFuture::join)
.collect(Collectors.joining(" ")); // Ground Control to Major Tom Take your protein pill and put your helmet on
CompletableFuture<String> future1 = CompletableFuture
.supplyAsync(() -> "Boris Volynov");
CompletableFuture<String> future2 = CompletableFuture
.supplyAsync(() -> "Major Tom");
CompletableFuture<String> future3 = CompletableFuture
.supplyAsync(() -> "Valentina Tereshkova");
CompletableFuture<Object> completableFuture = CompletableFuture.anyOf(future1, future2, future3);
completableFuture.get();
public class Message {
private String content;
private EnrichmentType enrichmentType;
public enum EnrichmentType {
MSISDN;
}
}
{
"action": "button_click",
"page": "book_card",
"msisdn": "88005553535"
}
{
"action": "button_click",
"page": "book_card",
"msisdn": "88005553535",
"enrichment": {
"firstName": "Vasya",
"lastName": "Ivanov"
}
}
public class EnrichmentService {
// возвращается обогащенный (или необогащенный content сообщения)
public String enrich(Message message) {...}
}
public class EnrichmentService {
// принцип DI нарушен
private final MessageValidator validator = new MessageValidatorImpl();
public String enrich(Message message) {...}
}
public class EnrichmentService {
// принцип DI НЕ нарушен
private final MessageValidator validator;
public EnrichmentService(MessageValidator validator) {
this.validator = validator;
}
public String enrich(Message message) {...}
}