chore: organize homework into first-part directory
|
After Width: | Height: | Size: 117 KiB |
|
After Width: | Height: | Size: 59 KiB |
@@ -0,0 +1,27 @@
|
||||
import java.util.Objects;
|
||||
|
||||
final class ImmutableClass {
|
||||
ImmutableClass(MutableClass firstField, String secondField, Integer thirdField) {
|
||||
this.firstField = new MutableClass(Objects.requireNonNull(firstField));
|
||||
this.secondField = secondField;
|
||||
this.thirdField = thirdField;
|
||||
}
|
||||
|
||||
public MutableClass getFirstField() {
|
||||
return new MutableClass(firstField);
|
||||
}
|
||||
|
||||
public String getSecondField() {
|
||||
// Копировать не нужно так как String является Immutable
|
||||
return secondField;
|
||||
}
|
||||
|
||||
public Integer getThirdField() {
|
||||
// Копировать не нужно так как Integer является Immutable
|
||||
return thirdField;
|
||||
}
|
||||
|
||||
private final MutableClass firstField;
|
||||
private final String secondField;
|
||||
private final Integer thirdField;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
class MutableClass {
|
||||
MutableClass(int value) {
|
||||
this.setValue(value);
|
||||
}
|
||||
|
||||
// Конструктор копирования
|
||||
public MutableClass(MutableClass other) {
|
||||
this.value = other.value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
private int value;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
# Homework 01
|
||||
|
||||
Реализовать свой иммутабельный класс, который будет
|
||||
внутри себя содержать поле с изменяемым классом.
|
||||
|
||||
## UPDATED
|
||||
|
||||
Иммутабельный класс должен содержать минимум 3 различных поля, включая поле с
|
||||
изменяемым классом.
|
||||
@@ -0,0 +1,61 @@
|
||||
# Emacs/vim
|
||||
|
||||
*~
|
||||
*.swp
|
||||
|
||||
# VSCode
|
||||
|
||||
.vscode
|
||||
.classpath
|
||||
.project
|
||||
.settings/
|
||||
|
||||
|
||||
# MacOS
|
||||
|
||||
.DS_Store
|
||||
|
||||
# CS56 specific: Secrets files
|
||||
|
||||
localhost.json
|
||||
heroku.json
|
||||
|
||||
# Maven (from: https://github.com/github/gitignore/blob/master/Maven.gitignore)
|
||||
|
||||
target/
|
||||
pom.xml.tag
|
||||
pom.xml.releaseBackup
|
||||
pom.xml.versionsBackup
|
||||
pom.xml.next
|
||||
release.properties
|
||||
dependency-reduced-pom.xml
|
||||
buildNumber.properties
|
||||
.mvn/timing.properties
|
||||
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
|
||||
.mvn/wrapper/maven-wrapper.jar
|
||||
|
||||
# Java (from: https://github.com/github/gitignore/blob/master/Java.gitignore)
|
||||
|
||||
# Compiled class file
|
||||
*.class
|
||||
|
||||
# Log file
|
||||
*.log
|
||||
|
||||
# BlueJ files
|
||||
*.ctxt
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.nar
|
||||
*.ear
|
||||
*.zip
|
||||
*.tar.gz
|
||||
*.rar
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
@@ -0,0 +1,29 @@
|
||||
# Homework 02
|
||||
|
||||
1. Создать класс Student, обязательное поле класса Student - List<Book> (минимум по 5 книг у каждого)
|
||||
|
||||
2. Создать текстовый файл со студентами и книгами
|
||||
|
||||
3. При помощи внутренних фреймворков и библиотек для ввода-вывода информации в Java считать содержимое файла и заполнить List<Student> этими данными (Должен быть реализован механизм заполнения коллекции студентов из текстового файла)
|
||||
|
||||
4. При помощи одного (не допускается объявления никаких промежуточных переменных, совсем никаких) стрима:
|
||||
|
||||
Вывести в консоль каждого студента (переопределите toString)
|
||||
|
||||
Получить для каждого студента список книг
|
||||
|
||||
Получить книги
|
||||
|
||||
Отсортировать книги по количеству страниц (Не забывайте про условия для сравнения объектов)
|
||||
|
||||
Оставить только уникальные книги
|
||||
|
||||
Отфильтровать книги, оставив только те, которые были выпущены после 2000 года
|
||||
|
||||
Ограничить стрим на 3 элементах
|
||||
|
||||
Получить из книг годы выпуска
|
||||
|
||||
При помощи методов короткого замыкания (почитайте самостоятельно что это такое) вернуть Optional от года
|
||||
|
||||
При помощи методов получения значения из Optional вывести в консоль год выпуска найденной книги, либо запись о том, что такая книга отсутствует
|
||||
@@ -0,0 +1 @@
|
||||
xargs img2pdf -o result.pdf < order.txt
|
||||
@@ -0,0 +1,10 @@
|
||||
Book{author='Ggg Ggg', title='Book Ggg', publishYear=2005, pageCount=100}
|
||||
Book{author='Bbb Bbb', title='Book Bbb', publishYear=2018, pageCount=200}
|
||||
Book{author='Ddd Ddd', title='Book Ddd', publishYear=2015, pageCount=400}
|
||||
Book{author='Aaa Aaa', title='Book Aaa', publishYear=2027, pageCount=500}
|
||||
Book{author='Iii Iii', title='Book Iii', publishYear=2012, pageCount=600}
|
||||
Book{author='Hhh Hhh', title='Book Hhh', publishYear=2021, pageCount=800}
|
||||
Book{author='Ccc Ccc', title='Book Ccc', publishYear=2024, pageCount=900}
|
||||
Book{author='Jjj Jjj', title='Book Jjj', publishYear=2001, pageCount=1000}
|
||||
Book{author='Lll Lll', title='Book Lll', publishYear=2025, pageCount=1100}
|
||||
Book{author='Fff Fff', title='Book Fff', publishYear=2030, pageCount=1200}
|
||||
@@ -0,0 +1,48 @@
|
||||
❮ mvn exec:java -Dexec.mainClass="com.example.App" > output.txt
|
||||
|
||||
[INFO] Scanning for projects...
|
||||
[INFO]
|
||||
[INFO] ---------------------< com.example:student-reader >---------------------
|
||||
[INFO] Building student-reader 1.0-SNAPSHOT
|
||||
[INFO] from pom.xml
|
||||
[INFO] --------------------------------[ jar ]---------------------------------
|
||||
[INFO]
|
||||
[INFO] --- exec:3.6.3:java (default-cli) @ student-reader ---
|
||||
Student{
|
||||
name='Aaa'
|
||||
surname='Bbb'
|
||||
books=
|
||||
Book{author='Aaa Aaa', title='Book Aaa', publishYear=2027, pageCount=500}
|
||||
Book{author='Bbb Bbb', title='Book Bbb', publishYear=2018, pageCount=200}
|
||||
Book{author='Ccc Ccc', title='Book Ccc', publishYear=2024, pageCount=900}
|
||||
Book{author='Ddd Ddd', title='Book Ddd', publishYear=2015, pageCount=400}
|
||||
Book{author='Ddd Ddd', title='Book Ddd', publishYear=2015, pageCount=400}
|
||||
}
|
||||
Student{
|
||||
name='Ccc'
|
||||
surname='Ddd'
|
||||
books=
|
||||
Book{author='Eee Eee', title='Book Eee', publishYear=1999, pageCount=300}
|
||||
Book{author='Fff Fff', title='Book Fff', publishYear=2030, pageCount=1200}
|
||||
Book{author='Ggg Ggg', title='Book Ggg', publishYear=2005, pageCount=100}
|
||||
Book{author='Hhh Hhh', title='Book Hhh', publishYear=2021, pageCount=800}
|
||||
Book{author='Iii Iii', title='Book Iii', publishYear=2012, pageCount=600}
|
||||
}
|
||||
Student{
|
||||
name='Eee'
|
||||
surname='Fff'
|
||||
books=
|
||||
Book{author='Aaa Aaa', title='Book Aaa', publishYear=2027, pageCount=500}
|
||||
Book{author='Bbb Bbb', title='Book Bbb', publishYear=2018, pageCount=200}
|
||||
Book{author='Jjj Jjj', title='Book Jjj', publishYear=2001, pageCount=1000}
|
||||
Book{author='Kkk Kkk', title='Book Kkk', publishYear=1995, pageCount=700}
|
||||
Book{author='Lll Lll', title='Book Lll', publishYear=2025, pageCount=1100}
|
||||
}
|
||||
Год выпуска: 2005
|
||||
Выполнение программы завершено
|
||||
[INFO] ------------------------------------------------------------------------
|
||||
[INFO] BUILD SUCCESS
|
||||
[INFO] ------------------------------------------------------------------------
|
||||
[INFO] Total time: 1.025 s
|
||||
[INFO] Finished at: 2026-08-06T23:30:03+04:00
|
||||
[INFO] ------------------------------------------------------------------------
|
||||
@@ -0,0 +1,7 @@
|
||||
"screenshots/Screenshot from 2026-08-06 23-28-36.png"
|
||||
"screenshots/Screenshot from 2026-08-06 23-29-11.png"
|
||||
"screenshots/Screenshot from 2026-08-06 23-29-31.png"
|
||||
"screenshots/Screenshot from 2026-08-06 23-52-39.png"
|
||||
"screenshots/Screenshot from 2026-08-06 23-35-03.png"
|
||||
"screenshots/Screenshot from 2026-08-06 23-26-45.png"
|
||||
"screenshots/Screenshot from 2026-08-06 23-31-03.png"
|
||||
|
After Width: | Height: | Size: 73 KiB |
|
After Width: | Height: | Size: 206 KiB |
|
After Width: | Height: | Size: 236 KiB |
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 268 KiB |
|
After Width: | Height: | Size: 207 KiB |
|
After Width: | Height: | Size: 256 KiB |
@@ -0,0 +1,39 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.example</groupId>
|
||||
<artifactId>student-reader</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<name>student-reader</name>
|
||||
<url>http://maven.apache.org</url>
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.20.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||
<version>2.20.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>21</maven.compiler.source>
|
||||
<maven.compiler.target>21</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.example;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Year;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class App {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
try {
|
||||
|
||||
Path studentsJsonFile = Path.of("students.json");
|
||||
List<Student> students = StudentReader.read(studentsJsonFile);
|
||||
|
||||
// Условие использования одного stream сохраняется
|
||||
students.stream()
|
||||
|
||||
// Вывести в консоль каждого студента (переопределите toString)
|
||||
.peek(System.out::println)
|
||||
|
||||
// Получить для каждого студента список книг
|
||||
.map(s -> s.getBooks()) // Stream<List<Book>>
|
||||
|
||||
// Получить книги
|
||||
.flatMap(List::stream) // Stream<Book>;
|
||||
|
||||
// Oтсортировать книги по количеству страниц (Не забывайте про условия для сравнения
|
||||
// объектов)
|
||||
.sorted(Comparator.comparingInt(Book::getPageCount))
|
||||
|
||||
// Оставить только уникальные книги
|
||||
.distinct()
|
||||
|
||||
// Отфильтровать книги, оставив только те, которые были выпущены после 2000 года
|
||||
.filter(b -> b.getPublishYear().isAfter(Year.of(2000)))
|
||||
|
||||
// Ограничить стрим на 3 элементах
|
||||
.limit(3)
|
||||
|
||||
// Получить из книг годы выпуска
|
||||
.map(Book::getPublishYear)
|
||||
|
||||
// При помощи методов короткого замыкания (почитайте самостоятельно что это такое) вернуть
|
||||
// Optional от года
|
||||
.findFirst()
|
||||
|
||||
// При помощи методов получения значения из Optional вывести в консоль год выпуска
|
||||
// найденной книги, либо запись о том, что такая книга отсутствует
|
||||
.ifPresentOrElse(
|
||||
year -> System.out.println("Год выпуска: " + year),
|
||||
() -> System.out.println("Подходящая книга отсутствует"));
|
||||
|
||||
} catch (IOException e) {
|
||||
|
||||
System.err.println("Сударь, вы передали неправильный файл!");
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
System.err.println("Ну тут мои полномочии всё!");
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
System.out.println("Выполнение программы завершено");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.example;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import java.time.Year;
|
||||
import java.util.Objects;
|
||||
|
||||
public class Book {
|
||||
|
||||
@JsonCreator
|
||||
public Book(
|
||||
@JsonProperty("author") String author,
|
||||
@JsonProperty("title") String title,
|
||||
@JsonProperty("publishYear") Year publishYear,
|
||||
@JsonProperty("pageCount") int pageCount) {
|
||||
|
||||
this.author = author;
|
||||
this.title = title;
|
||||
this.publishYear = publishYear;
|
||||
this.pageCount = pageCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(o instanceof Book book)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return pageCount == book.pageCount
|
||||
&& author.equals(book.author)
|
||||
&& title.equals(book.title)
|
||||
&& publishYear.equals(book.publishYear);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(author, title, publishYear, pageCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Book{"
|
||||
+ "author='"
|
||||
+ author
|
||||
+ '\''
|
||||
+ ", title='"
|
||||
+ title
|
||||
+ '\''
|
||||
+ ", publishYear="
|
||||
+ publishYear
|
||||
+ ", pageCount="
|
||||
+ pageCount
|
||||
+ '}';
|
||||
}
|
||||
|
||||
public int getPageCount() {
|
||||
return pageCount;
|
||||
}
|
||||
|
||||
public Year getPublishYear() {
|
||||
return publishYear;
|
||||
}
|
||||
|
||||
private final String author;
|
||||
private final String title;
|
||||
private final Year publishYear;
|
||||
private final int pageCount;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.example;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import java.util.List;
|
||||
|
||||
public class Student {
|
||||
|
||||
@JsonCreator
|
||||
public Student(
|
||||
@JsonProperty("name") String name,
|
||||
@JsonProperty("surname") String surname,
|
||||
@JsonProperty("books") List<Book> books) {
|
||||
|
||||
this.name = name;
|
||||
this.surname = surname;
|
||||
this.books = List.copyOf(books);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder booksString = new StringBuilder();
|
||||
|
||||
for (Book book : books) {
|
||||
booksString.append("\n ").append(book);
|
||||
}
|
||||
|
||||
return "Student{\n"
|
||||
+ " name='"
|
||||
+ name
|
||||
+ "'\n"
|
||||
+ " surname='"
|
||||
+ surname
|
||||
+ "'\n"
|
||||
+ " books="
|
||||
+ booksString
|
||||
+ "\n}";
|
||||
}
|
||||
|
||||
public List<Book> getBooks() {
|
||||
return books;
|
||||
}
|
||||
|
||||
private final String name;
|
||||
private final String surname;
|
||||
private final List<Book> books;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.example;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
public final class StudentReader {
|
||||
|
||||
public static List<Student> read(Path path) throws IOException {
|
||||
return MAPPER.readValue(path.toFile(), new TypeReference<List<Student>>() {});
|
||||
}
|
||||
|
||||
private StudentReader() {}
|
||||
|
||||
private static final ObjectMapper MAPPER =
|
||||
new ObjectMapper().registerModule(new JavaTimeModule());
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
[
|
||||
{
|
||||
"name": "Aaa",
|
||||
"surname": "Bbb",
|
||||
"books": [
|
||||
{
|
||||
"author": "Aaa Aaa",
|
||||
"title": "Book Aaa",
|
||||
"publishYear": "2027",
|
||||
"pageCount": 500
|
||||
},
|
||||
{
|
||||
"author": "Bbb Bbb",
|
||||
"title": "Book Bbb",
|
||||
"publishYear": "2018",
|
||||
"pageCount": 200
|
||||
},
|
||||
{
|
||||
"author": "Ccc Ccc",
|
||||
"title": "Book Ccc",
|
||||
"publishYear": "2024",
|
||||
"pageCount": 900
|
||||
},
|
||||
{
|
||||
"author": "Ddd Ddd",
|
||||
"title": "Book Ddd",
|
||||
"publishYear": "2015",
|
||||
"pageCount": 400
|
||||
},
|
||||
{
|
||||
"author": "Ddd Ddd",
|
||||
"title": "Book Ddd",
|
||||
"publishYear": "2015",
|
||||
"pageCount": 400
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Ccc",
|
||||
"surname": "Ddd",
|
||||
"books": [
|
||||
{
|
||||
"author": "Eee Eee",
|
||||
"title": "Book Eee",
|
||||
"publishYear": "1999",
|
||||
"pageCount": 300
|
||||
},
|
||||
{
|
||||
"author": "Fff Fff",
|
||||
"title": "Book Fff",
|
||||
"publishYear": "2030",
|
||||
"pageCount": 1200
|
||||
},
|
||||
{
|
||||
"author": "Ggg Ggg",
|
||||
"title": "Book Ggg",
|
||||
"publishYear": "2005",
|
||||
"pageCount": 100
|
||||
},
|
||||
{
|
||||
"author": "Hhh Hhh",
|
||||
"title": "Book Hhh",
|
||||
"publishYear": "2021",
|
||||
"pageCount": 800
|
||||
},
|
||||
{
|
||||
"author": "Iii Iii",
|
||||
"title": "Book Iii",
|
||||
"publishYear": "2012",
|
||||
"pageCount": 600
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Eee",
|
||||
"surname": "Fff",
|
||||
"books": [
|
||||
{
|
||||
"author": "Aaa Aaa",
|
||||
"title": "Book Aaa",
|
||||
"publishYear": "2027",
|
||||
"pageCount": 500
|
||||
},
|
||||
{
|
||||
"author": "Bbb Bbb",
|
||||
"title": "Book Bbb",
|
||||
"publishYear": "2018",
|
||||
"pageCount": 200
|
||||
},
|
||||
{
|
||||
"author": "Jjj Jjj",
|
||||
"title": "Book Jjj",
|
||||
"publishYear": "2001",
|
||||
"pageCount": 1000
|
||||
},
|
||||
{
|
||||
"author": "Kkk Kkk",
|
||||
"title": "Book Kkk",
|
||||
"publishYear": "1995",
|
||||
"pageCount": 700
|
||||
},
|
||||
{
|
||||
"author": "Lll Lll",
|
||||
"title": "Book Lll",
|
||||
"publishYear": "2025",
|
||||
"pageCount": 1100
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,147 @@
|
||||
# =========================
|
||||
# Gradle
|
||||
# =========================
|
||||
|
||||
.gradle/
|
||||
.gradle-tasknamecache
|
||||
gradle-app.setting
|
||||
|
||||
# Build directories
|
||||
bin/
|
||||
**/bin/
|
||||
out/
|
||||
**/out/
|
||||
build/
|
||||
**/build/
|
||||
target/
|
||||
**/target/
|
||||
|
||||
# Keep Gradle Wrapper files
|
||||
.gradle/wrapper/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!gradle/wrapper/gradle-wrapper.properties
|
||||
|
||||
# =========================
|
||||
# Java
|
||||
# =========================
|
||||
|
||||
# Compiled class files
|
||||
*.class
|
||||
|
||||
# Java package files
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
||||
|
||||
# Java temporary files
|
||||
*.ctxt
|
||||
*.mtj.tmp/
|
||||
|
||||
# JVM crash logs
|
||||
hs_err_pid*
|
||||
|
||||
|
||||
# =========================
|
||||
# IntelliJ IDEA
|
||||
# =========================
|
||||
|
||||
.idea/
|
||||
*.iws
|
||||
*.iml
|
||||
|
||||
# IDEA generated files
|
||||
*.idea/dataSources.ids
|
||||
*.idea/dataSources.local.xml
|
||||
*.idea/dataSources.xml
|
||||
*.idea/dictionaries/
|
||||
*.idea/dynamic.xml
|
||||
*.idea/gradle.xml
|
||||
*.idea/jsLibraryMappings.xml
|
||||
*.idea/libraries/
|
||||
*.idea/mongoSettings.xml
|
||||
*.idea/sqlDataSources.xml
|
||||
*.idea/tasks.xml
|
||||
*.idea/uiDesigner.xml
|
||||
*.idea/vcs.xml
|
||||
*.idea/workspace.xml
|
||||
*.idea_modules/
|
||||
|
||||
|
||||
# =========================
|
||||
# Eclipse / VS Code
|
||||
# =========================
|
||||
|
||||
.classpath
|
||||
.project
|
||||
.settings/
|
||||
|
||||
.vscode/
|
||||
|
||||
|
||||
# =========================
|
||||
# OS generated files
|
||||
# =========================
|
||||
|
||||
# macOS
|
||||
.DS_Store
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
.AppleDouble
|
||||
.DocumentRevisions-V100
|
||||
.LSOverride
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
._*
|
||||
.apdisk
|
||||
|
||||
# Windows
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
|
||||
|
||||
# =========================
|
||||
# IDE / Plugin generated files
|
||||
# =========================
|
||||
|
||||
Icon
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
|
||||
# =========================
|
||||
# Crashlytics / Fabric
|
||||
# =========================
|
||||
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics-build.properties
|
||||
crashlytics.properties
|
||||
fabric.properties
|
||||
|
||||
|
||||
# =========================
|
||||
# Temporary files
|
||||
# =========================
|
||||
|
||||
*~
|
||||
*.swp
|
||||
*.swo
|
||||
*.tmp
|
||||
|
||||
|
||||
# =========================
|
||||
# Build artifacts
|
||||
# =========================
|
||||
|
||||
dependency-reduced-pom.xml
|
||||
release.properties
|
||||
pom.xml.tag
|
||||
pom.xml.releaseBackup
|
||||
pom.xml.versionsBackup
|
||||
pom.xml.next
|
||||
|
||||
buildNumber.properties
|
||||
@@ -0,0 +1,3 @@
|
||||
# Homework 03
|
||||
|
||||
Реализовать паттерны: Стратегия, Цепочка обязанностей, Билдер, Прокси, Декоратор, Адаптер
|
||||
@@ -0,0 +1,21 @@
|
||||
❮ ./gradlew run > output.txt
|
||||
|
||||
Reusing configuration cache.
|
||||
> Task :app:processResources NO-SOURCE
|
||||
> Task :app:compileJava UP-TO-DATE
|
||||
> Task :app:classes UP-TO-DATE
|
||||
|
||||
> Task :app:run
|
||||
Был передан аргумент -568655464
|
||||
Product{first='first', second='second', third=3}
|
||||
ConcreteHandlerA обработал int: 42
|
||||
ConcreteHandlerB обработал String: Hello
|
||||
ConcreteComponent выполняет операцию
|
||||
ConcreteDecorator добавляет поведение
|
||||
ServiceProxy разрешает выполнение операции
|
||||
ConcreteService выполняет операцию
|
||||
ConcreteStrategyB выполняет операцию
|
||||
|
||||
BUILD SUCCESSFUL in 837ms
|
||||
2 actionable tasks: 1 executed, 1 up-to-date
|
||||
Configuration cache entry reused.
|
||||
@@ -0,0 +1,8 @@
|
||||
"screenshots/Screenshot from 2026-08-08 19-09-49.png"
|
||||
"screenshots/Screenshot from 2026-08-08 19-19-23.png"
|
||||
"screenshots/Screenshot from 2026-08-08 19-21-54.png"
|
||||
"screenshots/Screenshot from 2026-08-08 19-58-26.png"
|
||||
"screenshots/Screenshot from 2026-08-08 19-59-37.png"
|
||||
"screenshots/Screenshot from 2026-08-08 20-01-08.png"
|
||||
"screenshots/Screenshot from 2026-08-08 20-02-37.png"
|
||||
"screenshots/Screenshot from 2026-08-08 20-11-19.png"
|
||||
|
After Width: | Height: | Size: 109 KiB |
|
After Width: | Height: | Size: 256 KiB |
|
After Width: | Height: | Size: 183 KiB |
|
After Width: | Height: | Size: 118 KiB |
|
After Width: | Height: | Size: 103 KiB |
|
After Width: | Height: | Size: 123 KiB |
|
After Width: | Height: | Size: 253 KiB |
|
After Width: | Height: | Size: 81 KiB |
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env fish
|
||||
|
||||
set BASE app/src/main/java/org/example
|
||||
|
||||
# Создание директорий
|
||||
mkdir -p $BASE/{strategy,chain,builder,proxy,decorator,adapter}
|
||||
|
||||
# Strategy
|
||||
touch $BASE/strategy/Strategy.java
|
||||
touch $BASE/strategy/ConcreteStrategyA.java
|
||||
touch $BASE/strategy/ConcreteStrategyB.java
|
||||
touch $BASE/strategy/Context.java
|
||||
|
||||
# Chain of Responsibility
|
||||
touch $BASE/chain/Handler.java
|
||||
touch $BASE/chain/AbstractHandler.java
|
||||
touch $BASE/chain/ConcreteHandlerA.java
|
||||
touch $BASE/chain/ConcreteHandlerB.java
|
||||
|
||||
# Builder
|
||||
touch $BASE/builder/Product.java
|
||||
touch $BASE/builder/ProductBuilder.java
|
||||
|
||||
# Proxy
|
||||
touch $BASE/proxy/Service.java
|
||||
touch $BASE/proxy/RealService.java
|
||||
touch $BASE/proxy/ServiceProxy.java
|
||||
|
||||
# Decorator
|
||||
touch $BASE/decorator/Component.java
|
||||
touch $BASE/decorator/ConcreteComponent.java
|
||||
touch $BASE/decorator/Decorator.java
|
||||
touch $BASE/decorator/ConcreteDecorator.java
|
||||
|
||||
# Adapter
|
||||
touch $BASE/adapter/Target.java
|
||||
touch $BASE/adapter/Adaptee.java
|
||||
touch $BASE/adapter/Adapter.java
|
||||
|
||||
echo "Java pattern files created successfully!"
|
||||
@@ -0,0 +1,12 @@
|
||||
#
|
||||
# https://help.github.com/articles/dealing-with-line-endings/
|
||||
#
|
||||
# Linux start script should use lf
|
||||
/gradlew text eol=lf
|
||||
|
||||
# These are Windows script files and should use crlf
|
||||
*.bat text eol=crlf
|
||||
|
||||
# Binary files should be left untouched
|
||||
*.jar binary
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* This file was generated by the Gradle 'init' task.
|
||||
*
|
||||
* This generated file contains a sample Java application project to get you started.
|
||||
* For more details on building Java & JVM projects, please refer to https://docs.gradle.org/9.6.1/userguide/building_java_projects.html in the Gradle documentation.
|
||||
* This project uses @Incubating APIs which are subject to change.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
// Apply the application plugin to add support for building a CLI application in Java.
|
||||
application
|
||||
}
|
||||
|
||||
repositories {
|
||||
// Use Maven Central for resolving dependencies.
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// This dependency is used by the application.
|
||||
implementation(libs.guava)
|
||||
}
|
||||
|
||||
testing {
|
||||
suites {
|
||||
// Configure the built-in test suite
|
||||
val test = named<JvmTestSuite>("test") {
|
||||
// Use JUnit Jupiter test framework
|
||||
useJUnitJupiter("6.0.1")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply a specific Java toolchain to ease working on different environments.
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion = JavaLanguageVersion.of(21)
|
||||
}
|
||||
}
|
||||
|
||||
application {
|
||||
// Define the main class for the application.
|
||||
mainClass = "org.example.App"
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* This source file was generated by the Gradle 'init' task
|
||||
*/
|
||||
package org.example;
|
||||
|
||||
import org.example.adapter.*;
|
||||
import org.example.builder.*;
|
||||
import org.example.chain.*;
|
||||
import org.example.decorator.*;
|
||||
import org.example.proxy.*;
|
||||
import org.example.strategy.*;
|
||||
|
||||
public class App {
|
||||
public static void main(String[] args) {
|
||||
run();
|
||||
}
|
||||
|
||||
private static void run() {
|
||||
checkAdapterPattern();
|
||||
|
||||
checkBuilderPattern();
|
||||
|
||||
checkChainPattern();
|
||||
|
||||
checkDecoratorPattern();
|
||||
|
||||
checkProxyPattern();
|
||||
|
||||
checkStrategyPattern();
|
||||
}
|
||||
|
||||
private static void checkAdapterPattern() {
|
||||
Adaptee adaptee = new Adaptee();
|
||||
Target target = new Adapter(adaptee);
|
||||
|
||||
target.methodWithoutArguments();
|
||||
}
|
||||
|
||||
private static void checkBuilderPattern() {
|
||||
Product product =
|
||||
new ProductBuilder().setFirst("first").setSecond("second").setThird(3).build();
|
||||
|
||||
System.out.println(product);
|
||||
}
|
||||
|
||||
private static void checkChainPattern() {
|
||||
Handler handler = new ConcreteHandlerA();
|
||||
handler.setNext(new ConcreteHandlerB());
|
||||
|
||||
handler.handle(42);
|
||||
handler.handle("Hello");
|
||||
}
|
||||
|
||||
private static void checkDecoratorPattern() {
|
||||
Component component = new ConcreteComponent();
|
||||
Component decorator = new ConcreteDecorator(component);
|
||||
|
||||
decorator.operation();
|
||||
}
|
||||
|
||||
private static void checkProxyPattern() {
|
||||
Service service = new ConcreteService();
|
||||
Service proxy = new ServiceProxy(service);
|
||||
|
||||
proxy.execute();
|
||||
}
|
||||
|
||||
private static void checkStrategyPattern() {
|
||||
Context context = new Context(new ConcreteStrategyA());
|
||||
|
||||
boolean crayfishWhistled = true; // Если рак на горе свистнул
|
||||
|
||||
if (crayfishWhistled) {
|
||||
context.setStrategy(new ConcreteStrategyB());
|
||||
}
|
||||
|
||||
context.executeStrategy();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.example.adapter;
|
||||
|
||||
/** Adaptee */
|
||||
public class Adaptee {
|
||||
|
||||
public void methodWithArgument(int argument) {
|
||||
System.out.println("Был передан аргумент " + argument);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.example.adapter;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/** Adapter */
|
||||
public class Adapter implements Target {
|
||||
|
||||
public Adapter(Adaptee adaptee) {
|
||||
this.adaptee = adaptee;
|
||||
this.random = new Random();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void methodWithoutArguments() {
|
||||
int argument = random.nextInt();
|
||||
adaptee.methodWithArgument(argument);
|
||||
}
|
||||
|
||||
private final Adaptee adaptee;
|
||||
private Random random;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.example.adapter;
|
||||
|
||||
/** Target */
|
||||
public interface Target {
|
||||
|
||||
void methodWithoutArguments();
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package org.example.builder;
|
||||
|
||||
/** Product */
|
||||
public class Product {
|
||||
|
||||
public Product(String first, String second, int third) {
|
||||
this.first = first;
|
||||
this.second = second;
|
||||
this.third = third;
|
||||
}
|
||||
|
||||
public String getFirst() {
|
||||
return first;
|
||||
}
|
||||
|
||||
public String getSecond() {
|
||||
return second;
|
||||
}
|
||||
|
||||
public int getThird() {
|
||||
return third;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Product{"
|
||||
+ "first='"
|
||||
+ first
|
||||
+ '\''
|
||||
+ ", second='"
|
||||
+ second
|
||||
+ '\''
|
||||
+ ", third="
|
||||
+ third
|
||||
+ '}';
|
||||
}
|
||||
|
||||
private final String first;
|
||||
private final String second;
|
||||
private final int third;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package org.example.builder;
|
||||
|
||||
/** Builder */
|
||||
public class ProductBuilder {
|
||||
|
||||
public ProductBuilder setFirst(String first) {
|
||||
this.first = first;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProductBuilder setSecond(String second) {
|
||||
this.second = second;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProductBuilder setThird(int third) {
|
||||
this.third = third;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Product build() {
|
||||
return new Product(first, second, third);
|
||||
}
|
||||
|
||||
private String first;
|
||||
private String second;
|
||||
private int third;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.example.chain;
|
||||
|
||||
/** Abstract Handler */
|
||||
public abstract class AbstractHandler implements Handler {
|
||||
|
||||
@Override
|
||||
public void setNext(Handler handler) {
|
||||
this.next = handler;
|
||||
}
|
||||
|
||||
protected void handleNext(Object request) {
|
||||
if (next != null) {
|
||||
next.handle(request);
|
||||
}
|
||||
}
|
||||
|
||||
private Handler next;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.example.chain;
|
||||
|
||||
/** Concrete Handler A */
|
||||
public class ConcreteHandlerA extends AbstractHandler {
|
||||
|
||||
@Override
|
||||
public void handle(Object request) {
|
||||
if (request instanceof Integer) {
|
||||
System.out.println("ConcreteHandlerA обработал int: " + request);
|
||||
} else {
|
||||
handleNext(request);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.example.chain;
|
||||
|
||||
/** Concrete Handler B */
|
||||
public class ConcreteHandlerB extends AbstractHandler {
|
||||
|
||||
@Override
|
||||
public void handle(Object request) {
|
||||
if (request instanceof String) {
|
||||
System.out.println("ConcreteHandlerB обработал String: " + request);
|
||||
} else {
|
||||
handleNext(request);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.example.chain;
|
||||
|
||||
/** Handler */
|
||||
public interface Handler {
|
||||
void setNext(Handler handler);
|
||||
|
||||
void handle(Object request);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package org.example.decorator;
|
||||
|
||||
/** Component */
|
||||
public interface Component {
|
||||
void operation();
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.example.decorator;
|
||||
|
||||
/** Concrete Component */
|
||||
public class ConcreteComponent implements Component {
|
||||
|
||||
@Override
|
||||
public void operation() {
|
||||
System.out.println("ConcreteComponent выполняет операцию");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.example.decorator;
|
||||
|
||||
/** Concrete Decorator */
|
||||
public class ConcreteDecorator extends Decorator {
|
||||
|
||||
public ConcreteDecorator(Component component) {
|
||||
super(component);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void operation() {
|
||||
component.operation();
|
||||
System.out.println("ConcreteDecorator добавляет поведение");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.example.decorator;
|
||||
|
||||
/** Decorator */
|
||||
public abstract class Decorator implements Component {
|
||||
|
||||
protected Decorator(Component component) {
|
||||
this.component = component;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void operation() {
|
||||
component.operation();
|
||||
}
|
||||
|
||||
protected final Component component;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.example.proxy;
|
||||
|
||||
/** Concrete Service */
|
||||
public class ConcreteService implements Service {
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
System.out.println("ConcreteService выполняет операцию");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package org.example.proxy;
|
||||
|
||||
/** Service */
|
||||
public interface Service {
|
||||
void execute();
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.example.proxy;
|
||||
|
||||
/** Service Proxy */
|
||||
public class ServiceProxy implements Service {
|
||||
|
||||
public ServiceProxy(Service service) {
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
System.out.println("ServiceProxy разрешает выполнение операции");
|
||||
service.execute();
|
||||
}
|
||||
|
||||
private final Service service;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.example.strategy;
|
||||
|
||||
/** Concrete Strategy A */
|
||||
public class ConcreteStrategyA implements Strategy {
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
System.out.println("ConcreteStrategyA выполняет операцию");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.example.strategy;
|
||||
|
||||
/** Concrete Strategy B */
|
||||
public class ConcreteStrategyB implements Strategy {
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
System.out.println("ConcreteStrategyB выполняет операцию");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.example.strategy;
|
||||
|
||||
/** Context */
|
||||
public class Context {
|
||||
|
||||
public Context(Strategy strategy) {
|
||||
this.strategy = strategy;
|
||||
}
|
||||
|
||||
public void setStrategy(Strategy strategy) {
|
||||
this.strategy = strategy;
|
||||
}
|
||||
|
||||
public void executeStrategy() {
|
||||
strategy.execute();
|
||||
}
|
||||
|
||||
private Strategy strategy;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package org.example.strategy;
|
||||
|
||||
/** Strategy */
|
||||
public interface Strategy {
|
||||
void execute();
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
# This file was generated by the Gradle 'init' task.
|
||||
# https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_configuration_properties
|
||||
|
||||
org.gradle.configuration-cache=true
|
||||
org.gradle.parallel=true
|
||||
org.gradle.caching=true
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
# This file was generated by the Gradle 'init' task.
|
||||
# https://docs.gradle.org/current/userguide/version_catalogs.html#sec::toml-dependencies-format
|
||||
|
||||
[versions]
|
||||
guava = "33.5.0-jre"
|
||||
|
||||
[libraries]
|
||||
guava = { module = "com.google.guava:guava", version.ref = "guava" }
|
||||
@@ -0,0 +1,9 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip
|
||||
networkTimeout=10000
|
||||
retries=0
|
||||
retryBackOffMs=500
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
@@ -0,0 +1,248 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# gradlew start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh gradlew
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/<unknown>/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
@@ -0,0 +1,82 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem gradlew startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables, and ensure extensions are enabled
|
||||
setlocal EnableExtensions
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
"%COMSPEC%" /c exit 1
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
"%COMSPEC%" /c exit 1
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
|
||||
|
||||
@rem Execute gradlew
|
||||
@rem endlocal doesn't take effect until after the line is parsed and variables are expanded
|
||||
@rem which allows us to clear the local environment before executing the java command
|
||||
endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel
|
||||
|
||||
:exitWithErrorLevel
|
||||
@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts
|
||||
"%COMSPEC%" /c exit %ERRORLEVEL%
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* This file was generated by the Gradle 'init' task.
|
||||
*
|
||||
* The settings file is used to specify which projects to include in your build.
|
||||
* For more detailed information on multi-project builds, please refer to https://docs.gradle.org/9.6.1/userguide/multi_project_builds.html in the Gradle documentation.
|
||||
* This project uses @Incubating APIs which are subject to change.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
// Apply the foojay-resolver plugin to allow automatic download of JDKs
|
||||
id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0"
|
||||
}
|
||||
|
||||
rootProject.name = "project-root"
|
||||
include("app")
|
||||
@@ -0,0 +1,61 @@
|
||||
# Emacs/vim
|
||||
|
||||
*~
|
||||
*.swp
|
||||
|
||||
# VSCode
|
||||
|
||||
.vscode
|
||||
.classpath
|
||||
.project
|
||||
.settings/
|
||||
|
||||
|
||||
# MacOS
|
||||
|
||||
.DS_Store
|
||||
|
||||
# CS56 specific: Secrets files
|
||||
|
||||
localhost.json
|
||||
heroku.json
|
||||
|
||||
# Maven (from: https://github.com/github/gitignore/blob/master/Maven.gitignore)
|
||||
|
||||
target/
|
||||
pom.xml.tag
|
||||
pom.xml.releaseBackup
|
||||
pom.xml.versionsBackup
|
||||
pom.xml.next
|
||||
release.properties
|
||||
dependency-reduced-pom.xml
|
||||
buildNumber.properties
|
||||
.mvn/timing.properties
|
||||
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
|
||||
.mvn/wrapper/maven-wrapper.jar
|
||||
|
||||
# Java (from: https://github.com/github/gitignore/blob/master/Java.gitignore)
|
||||
|
||||
# Compiled class file
|
||||
*.class
|
||||
|
||||
# Log file
|
||||
*.log
|
||||
|
||||
# BlueJ files
|
||||
*.ctxt
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.nar
|
||||
*.ear
|
||||
*.zip
|
||||
*.tar.gz
|
||||
*.rar
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
|
After Width: | Height: | Size: 241 KiB |
|
After Width: | Height: | Size: 190 KiB |
|
After Width: | Height: | Size: 588 KiB |
|
After Width: | Height: | Size: 272 KiB |
@@ -0,0 +1,18 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.example</groupId>
|
||||
<artifactId>concurrency</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<name>concurrency</name>
|
||||
<url>http://maven.apache.org</url>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.example;
|
||||
|
||||
import com.example.util.ThreadUtils;
|
||||
|
||||
public class DeadLock {
|
||||
|
||||
private static final Object LOCK_A = new Object();
|
||||
private static final Object LOCK_B = new Object();
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
Thread thread1 =
|
||||
new Thread(
|
||||
() -> {
|
||||
synchronized (LOCK_A) {
|
||||
System.out.println("Thread 1: получил LOCK_A");
|
||||
|
||||
ThreadUtils.sleep(100);
|
||||
|
||||
System.out.println("Thread 1: пытается получить LOCK_B");
|
||||
|
||||
synchronized (LOCK_B) {
|
||||
System.out.println("Thread 1: получил LOCK_B");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Thread thread2 =
|
||||
new Thread(
|
||||
() -> {
|
||||
synchronized (LOCK_B) {
|
||||
System.out.println("Thread 2: получил LOCK_B");
|
||||
|
||||
ThreadUtils.sleep(100);
|
||||
|
||||
System.out.println("Thread 2: пытается получить LOCK_A");
|
||||
|
||||
synchronized (LOCK_A) {
|
||||
System.out.println("Thread 2: получил LOCK_A");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
thread1.start();
|
||||
thread2.start();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package com.example;
|
||||
|
||||
public class LiveLock {
|
||||
|
||||
static class Corridor {
|
||||
private Person currentPerson;
|
||||
|
||||
public Corridor(Person person) {
|
||||
currentPerson = person;
|
||||
}
|
||||
|
||||
public synchronized void setPerson(Person person) {
|
||||
currentPerson = person;
|
||||
}
|
||||
|
||||
public synchronized Person getPerson() {
|
||||
return currentPerson;
|
||||
}
|
||||
|
||||
public synchronized void pass() {
|
||||
System.out.printf("%s прошёл по коридору!%n", currentPerson.name);
|
||||
}
|
||||
}
|
||||
|
||||
static class Person {
|
||||
private final String name;
|
||||
private volatile boolean wantsToPass;
|
||||
|
||||
public Person(String personName) {
|
||||
name = personName;
|
||||
wantsToPass = true;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean wantsToPass() {
|
||||
return wantsToPass;
|
||||
}
|
||||
|
||||
public void walkThrough(Corridor corridor, Person otherPerson) {
|
||||
while (wantsToPass) {
|
||||
|
||||
// Если сейчас право пройти принадлежит другому человеку,
|
||||
// немного ждём и снова проверяем ситуацию.
|
||||
if (corridor.getPerson() != this) {
|
||||
try {
|
||||
Thread.sleep(1);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Если второй человек тоже хочет пройти,
|
||||
// вежливо уступаем ему дорогу.
|
||||
if (otherPerson.wantsToPass()) {
|
||||
System.out.printf("%s: Проходи первым, %s!%n", name, otherPerson.getName());
|
||||
|
||||
corridor.setPerson(otherPerson);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Если другой человек уже прошёл,
|
||||
// наконец сами идём по коридору.
|
||||
corridor.pass();
|
||||
wantsToPass = false;
|
||||
|
||||
System.out.printf("%s: Спасибо, %s!%n", name, otherPerson.getName());
|
||||
|
||||
corridor.setPerson(otherPerson);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
final Person ivan = new Person("Иван");
|
||||
final Person petr = new Person("Пётр");
|
||||
|
||||
// Изначально право пройти по коридору принадлежит Ивану.
|
||||
final Corridor corridor = new Corridor(ivan);
|
||||
|
||||
// Первый поток — Иван.
|
||||
new Thread(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ivan.walkThrough(corridor, petr);
|
||||
}
|
||||
})
|
||||
.start();
|
||||
|
||||
// Второй поток — Пётр.
|
||||
new Thread(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
petr.walkThrough(corridor, ivan);
|
||||
}
|
||||
})
|
||||
.start();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.example.util;
|
||||
|
||||
public class ThreadUtils {
|
||||
|
||||
public static void sleep(long millis) {
|
||||
try {
|
||||
Thread.sleep(millis);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.example;
|
||||
|
||||
public class TwoThreads {
|
||||
|
||||
private static final Object lock = new Object();
|
||||
private static boolean turnOne = true;
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
Thread thread1 =
|
||||
new Thread(
|
||||
() -> {
|
||||
while (true) {
|
||||
synchronized (lock) {
|
||||
while (!turnOne) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.print("1");
|
||||
turnOne = false;
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Thread thread2 =
|
||||
new Thread(
|
||||
() -> {
|
||||
while (true) {
|
||||
synchronized (lock) {
|
||||
while (turnOne) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.print("2");
|
||||
turnOne = true;
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
thread1.start();
|
||||
thread2.start();
|
||||
}
|
||||
}
|
||||