diff --git a/1.JavaSyntax/1.JavaSyntax.iml b/1.JavaSyntax/1.JavaSyntax.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/1.JavaSyntax/1.JavaSyntax.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/1.JavaSyntax/src/Quest.info b/1.JavaSyntax/src/Quest.info new file mode 100644 index 0000000..e4836af --- /dev/null +++ b/1.JavaSyntax/src/Quest.info @@ -0,0 +1 @@ +Синтаксис Java \ No newline at end of file diff --git a/2.JavaCore/src/com/javarush/task/task20/task2025/Solution.java b/2.JavaCore/src/com/javarush/task/task20/task2025/Solution.java index 468e549..b248954 100644 --- a/2.JavaCore/src/com/javarush/task/task20/task2025/Solution.java +++ b/2.JavaCore/src/com/javarush/task/task20/task2025/Solution.java @@ -10,7 +10,7 @@ public class Solution { private static int[][] matrix; private static void fillMatrix() { - int n = 11; + int n = 10; matrix = new int[n][n]; for (int i = 1; i < n; i++) { for (int j = 1; j < n; j++){ @@ -23,13 +23,14 @@ private static void fillMatrix() { } } - public static long[] getNumbers(long N) { - long[] result = null; + public static int[] getNumbers(long N) { + int[] result = null; + //long[] result = null; fillMatrix(); TreeSet list = new TreeSet(); - for (long i = 1; i <= N; i++) { + for (long i = 1; i < N; i++) { int power = 0; long tempNumber = i; boolean isNotChecked = false; @@ -67,15 +68,16 @@ public static long[] getNumbers(long N) { } if (!list.isEmpty()) { - result = new long[list.size()]; + result = new int[list.size()]; + //result = new long[list.size()]; int count = 0; for (long entry: list) { - result[count] = entry; + result[count] = (int) entry; count++; } return result; //return list.toArray(new Long[list.size() - 1]); - } else return new long[1]; + } else return new int[1]; } @@ -105,6 +107,7 @@ private static long getPoweredSumm(long number, int power) { public static void main(String[] args) { //long N = Long.MAX_VALUE; long baseN = 1000000; + //long N = 372; long N = 100000000; //long N = 146511208; @@ -112,13 +115,13 @@ public static void main(String[] args) { long startTime = new Date().getTime(); //Long[] result = getNumbersBaseAlg(baseN); //Long[] result = getNumbers(N); - long[] result = getNumbers(N); + int[] result = getNumbers(N); long endTime = new Date().getTime(); long memoryVolumeEnd = Runtime.getRuntime().freeMemory(); for (int i = 0; i < result.length ; i++) { System.out.println(result[i]); } - System.out.println("Memory consumption: " + ( ( memoryVolumeStart - memoryVolumeEnd ) / 1024 / 1024) + " Mb"); + System.out.println("Memory consumption: " + ( ( memoryVolumeStart - memoryVolumeEnd ) ) + " Mb"); System.out.println("Time consumption: " + (( endTime - startTime ) / 1000) + " s"); } } diff --git a/2.JavaCore/src/com/javarush/task/task20/task2026/Solution.java b/2.JavaCore/src/com/javarush/task/task20/task2026/Solution.java index 79f49af..d684518 100644 --- a/2.JavaCore/src/com/javarush/task/task20/task2026/Solution.java +++ b/2.JavaCore/src/com/javarush/task/task20/task2026/Solution.java @@ -16,6 +16,32 @@ public static void main(String[] args) { } public static int getRectangleCount(byte[][] a) { - return 0; + byte[][] temp; + temp = a.clone(); + for (int i = 0; i < temp.length; i++){ + for (int j = 0; j < temp.length - 1; j++){ + if (temp[i][j] == 1 && temp[i][j+1] == 1) { + temp[i][j] = 0; + } + } + } + + for (int i = 0; i < temp.length - 1; i++){ + for (int j = 0; j < temp.length; j++){ + if (temp[i][j] == 1 && temp[i+1][j] == 1) { + temp[i][j] = 0; + } + } + } + + int summ = 0; + for (int i = 0; i < temp.length; i++){ + for (int j = 0; j < temp.length; j++){ + if (temp[i][j] == 1) { + summ++; + } + } + } + return summ; } } diff --git "a/2.JavaCore/src/com/javarush/task/task20/task2026/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/2.JavaCore/src/com/javarush/task/task20/task2026/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" index 8716419..f0984cd 100644 --- "a/2.JavaCore/src/com/javarush/task/task20/task2026/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" +++ "b/2.JavaCore/src/com/javarush/task/task20/task2026/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -1,12 +1,21 @@ -
-

Алгоритмы-прямоугольники

-

1. Дан двумерный массив N*N, который содержит несколько прямоугольников.
-2. Различные прямоугольники не соприкасаются и не накладываются.
-3. Внутри прямоугольник весь заполнен 1.
-4. В массиве:
-4.1) a[i, j] = 1, если элемент (i, j) принадлежит какому-либо прямоугольнику
-4.2) a[i, j] = 0, в противном случае
-5. getRectangleCount должен возвращать количество прямоугольников.
-6. Метод main не участвует в тестировании

- -
+taskKey="com.javarush.task.task20.task2026" + +Алгоритмы-прямоугольники + +1. Дан двумерный массив N*N, который содержит несколько прямоугольников. +2. Различные прямоугольники не соприкасаются и не накладываются. +3. Внутри прямоугольник весь заполнен 1. +4. В массиве: +4.1) a[i, j] = 1, если элемент (i, j) принадлежит какому-либо прямоугольнику +4.2) a[i, j] = 0, в противном случае +5. getRectangleCount должен возвращать количество прямоугольников. +6. Метод main не участвует в тестировании + + +Требования: +1. В классе Solution должен существовать метод getRectangleCount с одним параметром типа byte[][]. +2. Метод getRectangleCount должен быть публичным. +3. Метод getRectangleCount должен быть статическим. +4. Метод getRectangleCount должен возвращать количество прямоугольников (в соответствии с заданием) найденное в полученном массиве. + + diff --git a/2.JavaCore/src/com/javarush/task/task20/task2027/Solution.java b/2.JavaCore/src/com/javarush/task/task20/task2027/Solution.java index 4cd979e..312bb4c 100644 --- a/2.JavaCore/src/com/javarush/task/task20/task2027/Solution.java +++ b/2.JavaCore/src/com/javarush/task/task20/task2027/Solution.java @@ -1,5 +1,6 @@ package com.javarush.task.task20.task2027; +import java.util.ArrayList; import java.util.List; /* @@ -20,11 +21,98 @@ public static void main(String[] args) { home - (5, 3) - (2, 0) same - (1, 1) - (4, 1) */ + } public static List detectAllWords(int[][] crossword, String... words) { + List list = new ArrayList<>(); + for (int k = 0; k < words.length; k++){ + Word resultString = new Word(words[k]); + for (int i = 0; i < crossword.length; i ++){ + for (int j = 0; j < crossword[0].length; j++){ + if (crossword[i][j] == words[k].charAt(0) ) { + + // Чтобы не заморачиваться проверкой выхода за границы массива, оборачиваем все обращения + // к ячейкам соседним с рассматриваемой ячейкой (в.т.ч. внутри метода сравнения) + + // Исходя из координат внутри массива 2ого символа слова, определяем вектор направления + // проверки на полное нахождение слова в массиве + try { + if (crossword[i][j + 1] == words[k].charAt(1)) { + checkMatch(list, crossword, words[k], resultString, 0, 1, i, j); + } + } catch (Exception e) { + } + try { + if (crossword[i - 1][j + 1] == words[k].charAt(1)) { + checkMatch(list, crossword, words[k], resultString, -1, 1, i, j); + } + } catch (Exception e) { + } + try { + if (crossword[i - 1][j] == words[k].charAt(1)) { + checkMatch(list, crossword, words[k], resultString, -1, 0, i, j); + } + } catch (Exception e) { + } + try { + if (crossword[i - 1][j - 1] == words[k].charAt(1)) { + checkMatch(list, crossword, words[k], resultString, -1, -1, i, j); + } + } catch (Exception e) { + } + try { + if (crossword[i][j - 1] == words[k].charAt(1)) { + checkMatch(list, crossword, words[k], resultString, 0, -1, i, j); + } + } catch (Exception e) { + } + try { + if (crossword[i + 1][j - 1] == words[k].charAt(1)) { + checkMatch(list, crossword, words[k], resultString, 1, -1, i, j); + } + } catch (Exception e) { + } + try { + if (crossword[i + 1][j] == words[k].charAt(1)) { + checkMatch(list, crossword, words[k], resultString, 1, 0, i, j); + } + } catch (Exception e) { + } + try { + if (crossword[i + 1][j + 1] == words[k].charAt(1)) { + checkMatch(list, crossword, words[k], resultString, 1, 1, i, j); + } + } catch (Exception e) { + } + } + + } + } + } + for (Word entry: list){ + System.out.println(entry.toString()); + } + return list; + } + + // Направление проверки получено, выполняем проверку для вхождения всего слова + private static void checkMatch(List list, int[][] crossword, String wordText,Word word, int deltaY, int deltaX, int startY, int startX) throws Exception{ + boolean isNotMatch = false; + int step = 1; + for (int i = 2; i < wordText.length(); i++){ + step++; + if (crossword[startY + step*deltaY][startX + step*deltaX] != wordText.charAt(i)) { + isNotMatch = true; + } - return null; + } + if (!isNotMatch){ + word.setStartPoint(startX, startY); + word.setEndPoint(startX + deltaX * step, startY + deltaY * step); + list.add(word); + word = new Word(wordText); + } } public static class Word { diff --git "a/2.JavaCore/src/com/javarush/task/task20/task2027/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/2.JavaCore/src/com/javarush/task/task20/task2027/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" index 7a38598..b0c319d 100644 --- "a/2.JavaCore/src/com/javarush/task/task20/task2027/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" +++ "b/2.JavaCore/src/com/javarush/task/task20/task2027/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -1,11 +1,21 @@ -
-

Кроссворд

-

1. Дан двумерный массив, который содержит буквы английского алфавита в нижнем регистре.
-2. Метод detectAllWords должен найти все слова из words в массиве crossword.
-3. Элемент(startX, startY) должен соответствовать первой букве слова, элемент(endX, endY) — последней.
-text — это само слово, располагается между начальным и конечным элементами
-4. Все слова есть в массиве.
-5. Слова могут быть расположены горизонтально, вертикально и по диагонали как в нормальном, так и в обратном порядке.
-6. Метод main не участвует в тестировании.

- -
+taskKey="com.javarush.task.task20.task2027" + +Кроссворд + +1. Дан двумерный массив, который содержит буквы английского алфавита в нижнем регистре. +2. Метод detectAllWords должен найти все слова из words в массиве crossword. +3. Элемент(startX, startY) должен соответствовать первой букве слова, элемент(endX, endY) - последней. +text - это само слово, располагается между начальным и конечным элементами +4. Все слова есть в массиве. +5. Слова могут быть расположены горизонтально, вертикально и по диагонали как в нормальном, так и в обратном порядке. +6. Метод main не участвует в тестировании. + + +Требования: +1. В классе Solution должен существовать метод detectAllWords. +2. В классе Solution должен существовать класс Word. +3. Метод detectAllWords должен быть статическим. +4. Метод detectAllWords должен быть публичным. +5. Метод detectAllWords должен возвращать список всех слов в кроссворде (согласно условию задачи). + + diff --git a/3.JavaMultithreading/3.JavaMultithreading.iml b/3.JavaMultithreading/3.JavaMultithreading.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/3.JavaMultithreading/3.JavaMultithreading.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/3.JavaMultithreading/src/Quest.info b/3.JavaMultithreading/src/Quest.info new file mode 100644 index 0000000..9ec72fe --- /dev/null +++ b/3.JavaMultithreading/src/Quest.info @@ -0,0 +1 @@ +Многопоточность в Java \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2301/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2301/Solution.java new file mode 100644 index 0000000..490f536 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2301/Solution.java @@ -0,0 +1,21 @@ +package com.javarush.task.task23.task2301; + +/* +Запрети наследование +*/ +public class Solution { + + public static final class Listener { + public void onMouseDown(int x, int y) { + //do something on mouse down event + } + + public void onMouseUp(int x, int y) { + //do something on mouse up event + } + } + + public static void main(String[] args) { + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2302/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2302/Solution.java new file mode 100644 index 0000000..bf0672c --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2302/Solution.java @@ -0,0 +1,21 @@ +package com.javarush.task.task23.task2302; + +/* +Запрети переопределение +*/ +public class Solution { + + public static class Listener { + public final void onMouseDown(int x, int y) { + //do something on mouse down event + } + + public void onMouseUp(int x, int y) { + //do something on mouse up event + } + } + + public static void main(String[] args) { + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2303/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2303/Solution.java new file mode 100644 index 0000000..17318f6 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2303/Solution.java @@ -0,0 +1,24 @@ +package com.javarush.task.task23.task2303; + +/* +Запрети создание экземпляров класса +*/ +public class Solution { + + public static abstract class Listener { + + public void onMouseDown(int x, int y) { + //do something on mouse down event + } + + public void onMouseUp(int x, int y) { + //do something on mouse up event + } + + + } + + public static void main(String[] args) { + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2304/DbMock.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2304/DbMock.java new file mode 100644 index 0000000..44fdbf9 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2304/DbMock.java @@ -0,0 +1,18 @@ +package com.javarush.task.task23.task2304; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class DbMock { + private static final List FAKE_TASKS = new ArrayList<>(); + private static final List FAKE_NAMES = new ArrayList<>(); + + public static List getFakeTasks(Map criteria) { + return ViewMock.getFakeTasksCriteria().equals(criteria) ? FAKE_TASKS : null; + } + + public static List getFakeNames(Map criteria) { + return ViewMock.getFakeNamesCriteria().equals(criteria) ? FAKE_NAMES : null; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2304/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2304/Solution.java new file mode 100644 index 0000000..50adfb6 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2304/Solution.java @@ -0,0 +1,51 @@ +package com.javarush.task.task23.task2304; + +import java.util.List; +import java.util.Map; + +/* +Inner 3 +*/ +public class Solution { + + private List tasks; + private List names; + + private DbDataProvider taskDataProvider = new TaskDataProvider(); + private DbDataProvider nameDataProvider = new NameDataProvider(); + + public void refresh() { + Map taskCriteria = ViewMock.getFakeTasksCriteria(); + taskDataProvider.refreshAllData(taskCriteria); + + Map nameCriteria = ViewMock.getFakeNamesCriteria(); + nameDataProvider.refreshAllData(nameCriteria); + } + + private interface DbDataProvider { + void refreshAllData(Map criteria); + } + + class Task { + } + + private class TaskDataProvider implements DbDataProvider{ + + @Override + public void refreshAllData(Map criteria) { + tasks = DbMock.getFakeTasks(criteria); + } + } + + private class NameDataProvider implements DbDataProvider{ + + @Override + public void refreshAllData(Map criteria) { + names = DbMock.getFakeNames(criteria); + } + } + + public static void main(String[] args) { + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2304/ViewMock.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2304/ViewMock.java new file mode 100644 index 0000000..53bb1cf --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2304/ViewMock.java @@ -0,0 +1,17 @@ +package com.javarush.task.task23.task2304; + +import java.util.HashMap; +import java.util.Map; + +public class ViewMock { + private static final Map FAKE_TASKS_CRITERIA = new HashMap(); + private static final Map FAKE_NAMES_CRITERIA = new HashMap(); + + public static Map getFakeTasksCriteria() { + return FAKE_TASKS_CRITERIA; + } + + public static Map getFakeNamesCriteria() { + return FAKE_NAMES_CRITERIA; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2305/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2305/Solution.java new file mode 100644 index 0000000..7f5cec6 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2305/Solution.java @@ -0,0 +1,26 @@ +package com.javarush.task.task23.task2305; + +/* +Inner +*/ +public class Solution { + public InnerClass[] innerClasses = new InnerClass[2]; + + public class InnerClass { + } + + public static Solution[] getTwoSolutions() { + Solution[] result = new Solution[2]; + for (int i = 0; i < 2; i++) { + Solution sol = new Solution(); + sol.innerClasses[0] = sol.new InnerClass(); + sol.innerClasses[1] = sol.new InnerClass(); + result[i] = sol; + } + return result; + } + + public static void main(String[] args) { + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2306/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2306/Solution.java new file mode 100644 index 0000000..0ff5356 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2306/Solution.java @@ -0,0 +1,46 @@ +package com.javarush.task.task23.task2306; + +/* +Inner 2 +*/ +public class Solution { + private String country; + private String city; + + public Solution(String country, String city) { + this.country = country; + this.city = city; + } + + /*т.к. модификатор иннер класса private, то чтобы вызвать метод getDescription из другого внешнего класса, + нужно обернуть его вызов в какой-то public метод*/ + public String getDescriptionOfUser(String name) { + return getTrickyUser(name).getDescription(); + } + + public SuperUser getTrickyUser(String name) { + return new SuperUser(name); + } + + private class SuperUser { + private String name; + + //доступ к этому методу возможен только внутри класса Solution, т.к. модификатор иннер класса private + public SuperUser(String name) { + this.name = name; + } + + //доступ к этому методу возможен только внутри класса Solution, т.к. модификатор иннер класса private + public String getDescription() { + return String.format("My name is %s. I'm from %s, %s.", this.name, country, city); + } + } + + public static void main(String[] args) { + Solution solution = new Solution("the USA", "Seattle"); + //внутри класса Solution (а сейчас мы внутри) к методу getDescription можно обращаться обоими способами + System.out.println(solution.getTrickyUser("George").getDescription()); + //а из любого другого внешнего класса только так: + System.out.println(solution.getDescriptionOfUser("George")); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2307/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2307/Solution.java new file mode 100644 index 0000000..6d37e68 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2307/Solution.java @@ -0,0 +1,22 @@ +package com.javarush.task.task23.task2307; + +/* +Как выбрать нужное? +*/ +public class Solution { + public static final String TEST = "test"; + + public static class TEST { + @Override + public String toString() { + return "test class"; + } + } + + static Object obj; + + public static void main(String[] args) { + obj = new Solution.TEST(); + System.out.println(obj); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2308/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2308/Solution.java new file mode 100644 index 0000000..1d6f309 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2308/Solution.java @@ -0,0 +1,59 @@ +package com.javarush.task.task23.task2308; + +/* +Рефакторинг, вложенные классы +*/ +public class Solution { + public class ServerNotAccessibleException extends Exception { + public ServerNotAccessibleException() { + super(Constants.SERVER_IS_NOT_ACCESSIBLE_FOR_NOW); + } + + public ServerNotAccessibleException(Throwable cause) { + super(Constants.SERVER_IS_NOT_ACCESSIBLE_FOR_NOW, cause); + } + } + + public class UnauthorizedUserException extends Exception { + public UnauthorizedUserException() { + super(Constants.USER_IS_NOT_AUTHORIZED); + } + + public UnauthorizedUserException(Throwable cause) { + super(Constants.USER_IS_NOT_AUTHORIZED, cause); + } + } + + public class BannedUserException extends Exception { + public BannedUserException() { + super(Constants.USER_IS_BANNED); + } + + public BannedUserException(Throwable cause) { + super(Constants.USER_IS_BANNED, cause); + } + } + + public class RestrictionException extends Exception { + public RestrictionException() { + super(Constants.ACCESS_IS_DENIED); + } + + public RestrictionException(Throwable cause) { + super(Constants.ACCESS_IS_DENIED, cause); + } + } + + public static final class Constants{ + + public static final String SERVER_IS_NOT_ACCESSIBLE_FOR_NOW = "Server is not accessible for now."; + public static final String USER_IS_NOT_AUTHORIZED = "User is not authorized."; + public static final String USER_IS_BANNED = "User is banned."; + public static final String ACCESS_IS_DENIED = "Access is denied."; + + } + + public static void main(String[] args) { + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2309/AbstractDbSelectExecutor.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/AbstractDbSelectExecutor.java new file mode 100644 index 0000000..0adab74 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/AbstractDbSelectExecutor.java @@ -0,0 +1,45 @@ +package com.javarush.task.task23.task2309; + +import com.javarush.task.task23.task2309.vo.*; + +import java.lang.reflect.ParameterizedType; +import java.util.ArrayList; +import java.util.List; + +public abstract class AbstractDbSelectExecutor { + + public abstract String getQuery(); + + /** + * It's fake method + * + * @return a list of 5 fake items + */ + public List execute() { + List result = new ArrayList<>(); + //assert the query is not null + String query = getQuery(); + if (query == null) return result; + + try { + //generate 5 fake items + for (int i = 1; i <= 5; i++) { + T newItem = getNewInstanceOfGenericType(); + newItem.setId(i); + newItem.setName(newItem.getClass().getSimpleName() + "-" + i); + newItem.setDescription("Got by executing '" + query + "'"); + result.add(newItem); + } + } catch (InstantiationException | IllegalAccessException e) { + e.printStackTrace(); + } + return result; + } + + //reflection + //you have to know that it is possible to create new instance of T (generic type) class by using its default constructor + private T getNewInstanceOfGenericType() throws InstantiationException, IllegalAccessException { + return (T) ((Class) ((ParameterizedType) this.getClass(). + getGenericSuperclass()).getActualTypeArguments()[0]).newInstance(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2309/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/Solution.java new file mode 100644 index 0000000..ad0ec87 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/Solution.java @@ -0,0 +1,82 @@ +package com.javarush.task.task23.task2309; + +import com.javarush.task.task23.task2309.vo.*; + +import java.lang.reflect.ParameterizedType; +import java.util.List; + +/* +Анонимность иногда так приятна! +*/ +public class Solution { + public static void main(String[] args) { + Solution solution = new Solution(); + print(solution.getUsers()); + print(solution.getLocations()); + } + + public static void print(List list) { + String format = "Id=%d, name='%s', description=%s"; + for (Object obj : list) { + NamedItem item = (NamedItem) obj; + System.out.println(String.format(format, item.getId(), item.getName(), item.getDescription())); + } + } + + public List getUsers() { + return new AbstractDbSelectExecutor(){ + + @Override + public String getQuery() { + + return "SELECT * FROM " + ((Class) ((ParameterizedType) this.getClass(). + getGenericSuperclass()).getActualTypeArguments()[0]).getSimpleName().toUpperCase(); + } + }.execute(); + } + + public List getLocations() { + return new AbstractDbSelectExecutor(){ + + @Override + public String getQuery() { + return "SELECT * FROM " + ((Class) ((ParameterizedType) this.getClass(). + getGenericSuperclass()).getActualTypeArguments()[0]).getSimpleName().toUpperCase(); + } + }.execute(); + } + + public List getServers() { + return new AbstractDbSelectExecutor(){ + + @Override + public String getQuery() { + return "SELECT * FROM " + ((Class) ((ParameterizedType) this.getClass(). + getGenericSuperclass()).getActualTypeArguments()[0]).getSimpleName().toUpperCase(); + } + }.execute(); + } + + public List getSubjects() { + return new AbstractDbSelectExecutor(){ + + @Override + public String getQuery() { + return "SELECT * FROM " + ((Class) ((ParameterizedType) this.getClass(). + getGenericSuperclass()).getActualTypeArguments()[0]).getSimpleName().toUpperCase(); + } + }.execute(); + } + + public List getSubscriptions() { + return new AbstractDbSelectExecutor(){ + + @Override + public String getQuery() { + return "SELECT * FROM " + ((Class) ((ParameterizedType) this.getClass(). + getGenericSuperclass()).getActualTypeArguments()[0]).getSimpleName().toUpperCase(); + } + }.execute(); + } + +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/Location.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/Location.java new file mode 100644 index 0000000..b035eab --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/Location.java @@ -0,0 +1,7 @@ +package com.javarush.task.task23.task2309.vo; + +/** + * Created by ArchMage on 02.03.17. + */ +public class Location extends NamedItem { +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/NamedItem.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/NamedItem.java new file mode 100644 index 0000000..9a788e1 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/NamedItem.java @@ -0,0 +1,34 @@ +package com.javarush.task.task23.task2309.vo; + +public class NamedItem { + private int id; + private String name; + private String description; + + public NamedItem() { + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/Server.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/Server.java new file mode 100644 index 0000000..160a41e --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/Server.java @@ -0,0 +1,7 @@ +package com.javarush.task.task23.task2309.vo; + +/** + * Created by ArchMage on 02.03.17. + */ +public class Server extends NamedItem { +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/Subject.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/Subject.java new file mode 100644 index 0000000..ae6121b --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/Subject.java @@ -0,0 +1,7 @@ +package com.javarush.task.task23.task2309.vo; + +/** + * Created by ArchMage on 02.03.17. + */ +public class Subject extends NamedItem { +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/Subscription.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/Subscription.java new file mode 100644 index 0000000..405d441 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/Subscription.java @@ -0,0 +1,7 @@ +package com.javarush.task.task23.task2309.vo; + +/** + * Created by ArchMage on 02.03.17. + */ +public class Subscription extends NamedItem { +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/User.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/User.java new file mode 100644 index 0000000..da2eedf --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2309/vo/User.java @@ -0,0 +1,7 @@ +package com.javarush.task.task23.task2309.vo; + +/** + * Created by ArchMage on 02.03.17. + */ +public class User extends NamedItem { +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2310/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2310/Solution.java new file mode 100644 index 0000000..b72195f --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2310/Solution.java @@ -0,0 +1,32 @@ +package com.javarush.task.task23.task2310; + +/* +Напряги извилины! +*/ +public class Solution { + private String name; + + Solution(String name) { + this.name = name; + } + + protected String getName() { + return name; + } + + private void sout() { + new Solution("sout") { + + + void printName() { + System.out.println(getName()); + } + + + }.printName(); + } + + public static void main(String[] args) { + new Solution("main").sout(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2311/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2311/Solution.java new file mode 100644 index 0000000..2b5a633 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2311/Solution.java @@ -0,0 +1,52 @@ +package com.javarush.task.task23.task2311; + +/* +Повторяем threads +*/ +public class Solution { + public final String name; + public final String food; + public final String sound; + + public Solution(String name, String food, String sound) { + this.name = name; + this.food = food; + this.sound = sound; + } + + public void eat() { + System.out.println(name + ": Mmmmm, " + food); + } + + public void play() { + System.out.println(name + ": " + sound + " " + sound); + } + + public void sleep(long milliseconds) { + System.out.println(name + ": Zzzzzzz..." + (milliseconds / 1000) + " sec"); + } + + public void live() throws InterruptedException { + Thread thread = new Thread() { + public void run() { + try { + someActions(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void someActions() throws InterruptedException { + eat(); + play(); + Solution.this.sleep(1000); + } + }; + thread.start(); + thread.join(); + } + + public static void main(String[] args) throws InterruptedException { + new Solution("Amigo", "beef", "knock").live(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2312/KeyboardObserver.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/KeyboardObserver.java new file mode 100644 index 0000000..0ff7a16 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/KeyboardObserver.java @@ -0,0 +1,81 @@ +package com.javarush.task.task23.task2312; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.util.Queue; +import java.util.concurrent.ArrayBlockingQueue; + +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; + +public class KeyboardObserver extends Thread +{ + private Queue keyEvents = new ArrayBlockingQueue(100); + + private JFrame frame; + + @Override + public void run() + { + frame = new JFrame("KeyPress Tester"); + frame.setTitle("Transparent JFrame Demo"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + frame.setUndecorated(true); + frame.setSize(400, 400); + frame.setExtendedState(JFrame.MAXIMIZED_BOTH); + frame.setLayout(new GridBagLayout()); + + frame.setOpacity(0.0f); + frame.setVisible(true); + + frame.addFocusListener(new FocusListener() + { + @Override + public void focusGained(FocusEvent e) + { + //do nothing + } + + @Override + public void focusLost(FocusEvent e) + { + System.exit(0); + } + }); + + + frame.addKeyListener(new KeyListener() + { + + public void keyTyped(KeyEvent e) + { + //do nothing + } + + public void keyReleased(KeyEvent e) + { + //do nothing + } + + public void keyPressed(KeyEvent e) + { + keyEvents.add(e); + } + }); + } + + + public boolean hasKeyEvents() + { + return !keyEvents.isEmpty(); + } + + public KeyEvent getEventFromTop() + { + return keyEvents.poll(); + } +} + diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2312/Mouse.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/Mouse.java new file mode 100644 index 0000000..2795c84 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/Mouse.java @@ -0,0 +1,19 @@ +package com.javarush.task.task23.task2312; + +public class Mouse { + private int x; + private int y; + + public Mouse(int x, int y) { + this.x = x; + this.y = y; + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2312/Room.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/Room.java new file mode 100644 index 0000000..e42d0a7 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/Room.java @@ -0,0 +1,168 @@ +package com.javarush.task.task23.task2312; + + +import java.awt.event.KeyEvent; +import java.util.ArrayList; + +/** + * Основной класс программы. + */ +public class Room { + private int width; + private int height; + private Snake snake; + private Mouse mouse; + + public Room(int width, int height, Snake snake) { + this.width = width; + this.height = height; + this.snake = snake; + } + + public Snake getSnake() { + return snake; + } + + public Mouse getMouse() { + return mouse; + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public void setWidth(int width) { + this.width = width; + } + + public void setHeight(int height) { + this.height = height; + } + + public void setSnake(Snake snake) { + this.snake = snake; + } + + public void setMouse(Mouse mouse) { + this.mouse = mouse; + } + + /** + * Основной цикл программы. + * Тут происходят все важные действия + */ + public void run() { + //Создаем объект "наблюдатель за клавиатурой" и стартуем его. + KeyboardObserver keyboardObserver = new KeyboardObserver(); + keyboardObserver.start(); + + //пока змея жива + while (snake.isAlive()) { + //"наблюдатель" содержит события о нажатии клавиш? + if (keyboardObserver.hasKeyEvents()) { + KeyEvent event = keyboardObserver.getEventFromTop(); + //Если равно символу 'q' - выйти из игры. + if (event.getKeyChar() == 'q') return; + + //Если "стрелка влево" - сдвинуть фигурку влево + if (event.getKeyCode() == KeyEvent.VK_LEFT) + snake.setDirection(SnakeDirection.LEFT); + //Если "стрелка вправо" - сдвинуть фигурку вправо + else if (event.getKeyCode() == KeyEvent.VK_RIGHT) + snake.setDirection(SnakeDirection.RIGHT); + //Если "стрелка вверх" - сдвинуть фигурку вверх + else if (event.getKeyCode() == KeyEvent.VK_UP) + snake.setDirection(SnakeDirection.UP); + //Если "стрелка вниз" - сдвинуть фигурку вниз + else if (event.getKeyCode() == KeyEvent.VK_DOWN) + snake.setDirection(SnakeDirection.DOWN); + } + + snake.move(); //двигаем змею + print(); //отображаем текущее состояние игры + sleep(); //пауза между ходами + } + + //Выводим сообщение "Game Over" + System.out.println("Game Over!"); + } + + /** + * Выводим на экран текущее состояние игры + */ + public void print() { + //Создаем массив, куда будем "рисовать" текущее состояние игры + int[][] matrix = new int[height][width]; + + //Рисуем все кусочки змеи + ArrayList sections = new ArrayList(snake.getSections()); + for (SnakeSection snakeSection : sections) { + matrix[snakeSection.getY()][snakeSection.getX()] = 1; + } + + //Рисуем голову змеи (4 - если змея мертвая) + matrix[snake.getY()][snake.getX()] = snake.isAlive() ? 2 : 4; + + //Рисуем мышь + matrix[mouse.getY()][mouse.getX()] = 3; + + //Выводим все это на экран + String[] symbols = {" . ", " x ", " X ", "^_^", "RIP"}; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + System.out.print(symbols[matrix[y][x]]); + } + System.out.println(); + } + System.out.println(); + System.out.println(); + System.out.println(); + } + + /** + * Метод вызывается, когда мышь съели + */ + public void eatMouse() { + createMouse(); + } + + /** + * Создает новую мышь + */ + public void createMouse() { + int x = (int) (Math.random() * width); + int y = (int) (Math.random() * height); + + mouse = new Mouse(x, y); + } + + + public static Room game; + + public static void main(String[] args) { + game = new Room(20, 20, new Snake(10, 10)); + game.snake.setDirection(SnakeDirection.DOWN); + game.createMouse(); + game.run(); + } + + + private int initialDelay = 520; + private int delayStep = 20; + + /** + * Программа делает паузу, длинна которой зависит от длинны змеи. + */ + public void sleep() { + try { + int level = snake.getSections().size(); + int delay = level < 15 ? (initialDelay - delayStep * level) : 200; + Thread.sleep(delay); + } catch (InterruptedException e) { + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2312/Snake.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/Snake.java new file mode 100644 index 0000000..6d22156 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/Snake.java @@ -0,0 +1,79 @@ +package com.javarush.task.task23.task2312; + +import java.util.ArrayList; +import java.util.List; + + + +/** + * Created by ArchMage on 27.02.17. + */ +public class Snake { + private List sections; + private boolean isAlive; + private SnakeDirection direction; + + public List getSections() { + return sections; + } + + public boolean isAlive() { + return isAlive; + } + + public SnakeDirection getDirection() { + return direction; + } + + public void setDirection(SnakeDirection direction) { + this.direction = direction; + } + + public Snake(int x, int y) { + sections = new ArrayList(); + sections.add(new SnakeSection(x,y)); + isAlive = true; + } + + public int getX(){ + return sections.get(0).getX(); + } + + public int getY() { + return sections.get(0).getY(); + } + + public void move() { + if (!isAlive) return; + + if (direction == SnakeDirection.UP) + move(0, -1); + else if (direction == SnakeDirection.RIGHT) + move(1, 0); + else if (direction == SnakeDirection.DOWN) + move(0, 1); + else if (direction == SnakeDirection.LEFT) + move(-1, 0); + } + + public void move(int x, int y) { + SnakeSection head = sections.get(0); + head = new SnakeSection(head.getX() + x, getY() + y); + checkBorders(head); + if (!isAlive) return; + checkBody(head); + if (!isAlive) return; + } + + public void checkBorders(SnakeSection head) { + if ((head.getX() < 0 || head.getX() >= Room.game.getWidth()) || + (head.getY() < 0 || head.getY() >= Room.game.getHeight())) { + isAlive = false; + } + } + + + public void checkBody(SnakeSection head) { + if (sections.contains(head)) { isAlive = false;} + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2312/SnakeDirection.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/SnakeDirection.java new file mode 100644 index 0000000..d8a3b0d --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/SnakeDirection.java @@ -0,0 +1,9 @@ +package com.javarush.task.task23.task2312; + + +public enum SnakeDirection { + UP, + RIGHT, + DOWN, + LEFT +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task23/task2312/SnakeSection.java b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/SnakeSection.java new file mode 100644 index 0000000..17f3977 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task23/task2312/SnakeSection.java @@ -0,0 +1,40 @@ +package com.javarush.task.task23.task2312; + +public class SnakeSection { + private int x; + private int y; + + + public SnakeSection(int x, int y) { + this.x = x; + this.y = y; + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + SnakeSection that = (SnakeSection) o; + + if (x != that.x) return false; + if (y != that.y) return false; + return true; + + } + + @Override + public int hashCode() { + int result = x; + result = 31 * result + y; + return result; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2401/SelfInterfaceMarker.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2401/SelfInterfaceMarker.java new file mode 100644 index 0000000..ffa8084 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2401/SelfInterfaceMarker.java @@ -0,0 +1,7 @@ +package com.javarush.task.task24.task2401; + +/** + * Created by PAKOT on 08.03.2017. + */ +public interface SelfInterfaceMarker { +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2401/SelfInterfaceMarkerImpl.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2401/SelfInterfaceMarkerImpl.java new file mode 100644 index 0000000..3c1af58 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2401/SelfInterfaceMarkerImpl.java @@ -0,0 +1,14 @@ +package com.javarush.task.task24.task2401; + +/** + * Created by PAKOT on 08.03.2017. + */ +public class SelfInterfaceMarkerImpl implements SelfInterfaceMarker { + public void sowSomething(){ + System.out.println("Something"); + } + + public void calc(int i, int b){ + System.out.println(i + b); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2401/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2401/Solution.java new file mode 100644 index 0000000..3781821 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2401/Solution.java @@ -0,0 +1,12 @@ +package com.javarush.task.task24.task2401; + +/* +Создание своего интерфейса-маркера +*/ +public class Solution { + public static void main(String[] args) throws UnsupportedInterfaceMarkerException { + SelfInterfaceMarkerImpl obj = new SelfInterfaceMarkerImpl(); + Util.testClass(obj); + } + +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2401/UnsupportedInterfaceMarkerException.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2401/UnsupportedInterfaceMarkerException.java new file mode 100644 index 0000000..cb347a1 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2401/UnsupportedInterfaceMarkerException.java @@ -0,0 +1,7 @@ +package com.javarush.task.task24.task2401; + +/** + * Created by PAKOT on 08.03.2017. + */ +public class UnsupportedInterfaceMarkerException extends Exception { +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2401/Util.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2401/Util.java new file mode 100644 index 0000000..f3b95c1 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2401/Util.java @@ -0,0 +1,16 @@ +package com.javarush.task.task24.task2401; + +import java.lang.reflect.Method; + +public class Util { + //пример того, как можно использовать интерфейс-маркер + //this method is available only for a SelfInterfaceMarker implementation + public static void testClass(SelfInterfaceMarker interfaceMarker) throws UnsupportedInterfaceMarkerException { + if (interfaceMarker == null) throw new UnsupportedInterfaceMarkerException(); + + for (Method method : interfaceMarker.getClass().getDeclaredMethods()) { + System.out.println(method); + } + } + +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task24/task2401/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task24/task2401/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..05805d7 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task24/task2401/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,11 @@ +taskKey="com.javarush.task.task24.task2401" + +Создание своего интерфейса-маркера + +1. Создай интерфейс-маркер SelfInterfaceMarker. +2. Создай класс SelfInterfaceMarkerImpl, который реализует SelfInterfaceMarker. +3. Добавь в SelfInterfaceMarkerImpl минимум 2 любых public метода. +4. Создай исключение UnsupportedInterfaceMarkerException, унаследуй его от класса Exception. +5. В методе testClass класса Util: если параметр == null, то выбросьте UnsupportedInterfaceMarkerException. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2402/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2402/Solution.java new file mode 100644 index 0000000..bdfa9d6 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2402/Solution.java @@ -0,0 +1,46 @@ +package com.javarush.task.task24.task2402; + +/* +Cloneable +*/ +public class Solution { + + public static void main(String[] args) throws CloneNotSupportedException { + Test1 test1 = new Test1(); + test1.clone(); + + Test2 test2 = new Test2(); + test2.clone(new Test2()); + + Test3 test3 = new Test3(); + test3.c1one(); + + Test4 test4 = new Test4(); + test4.clone(); + } + + + public static class Test1 implements Cloneable{ + protected Test1 clone() throws CloneNotSupportedException { + return (Test1)super.clone(); + } + } + + public static class Test2 extends Test1 { + public Test2 clone(Test2 test2) throws CloneNotSupportedException { + return (Test2)test2.clone(); + } + } + + public static class Test3 { + protected Object c1one() throws CloneNotSupportedException { + return new Test3(); + } + } + + public static class Test4 extends Test3 implements Cloneable { + protected Object clone() throws CloneNotSupportedException { + return super.c1one(); + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task24/task2402/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task24/task2402/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..08a4012 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task24/task2402/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,7 @@ +taskKey="com.javarush.task.task24.task2402" + +Cloneable + +Добавьте java-код, чтобы метод main отработал без исключений. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2403/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2403/Solution.java new file mode 100644 index 0000000..338637b --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2403/Solution.java @@ -0,0 +1,33 @@ +package com.javarush.task.task24.task2403; + +import java.io.Serializable; +import java.rmi.Remote; +import java.rmi.server.RemoteObject; +import java.util.ArrayDeque; +import java.util.EventListener; + +/* +Так-с... сопоставим +*/ +public class Solution { + public static class A implements Serializable { + } + + public static class B implements Remote { + } + + public static class C extends ArrayDeque { + public C clone() { + return (C) super.clone(); + } + } + + public static class D implements EventListener { + } + + + + public static void main(String[] args) { + + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task24/task2403/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task24/task2403/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..03bd329 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task24/task2403/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,9 @@ +taskKey="com.javarush.task.task24.task2403" + +Так-с... сопоставим + +Исправь ошибки: перемести методы clone в те классы, в которых они должны быть реализованы. +Лишние методы удали. +Не удаляй метод main. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2404/HasHeight.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2404/HasHeight.java new file mode 100644 index 0000000..cad7932 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2404/HasHeight.java @@ -0,0 +1,5 @@ +package com.javarush.task.task24.task2404; + +public interface HasHeight { + double getHeight(); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2404/HasWidth.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2404/HasWidth.java new file mode 100644 index 0000000..8aff6ef --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2404/HasWidth.java @@ -0,0 +1,5 @@ +package com.javarush.task.task24.task2404; + +public interface HasWidth { + double getWidth(); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2404/Point.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2404/Point.java new file mode 100644 index 0000000..dbb27ad --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2404/Point.java @@ -0,0 +1,19 @@ +package com.javarush.task.task24.task2404; + +public class Point { + private double x; + private double y; + + public Point(double x, double y) { + this.x = x; + this.y = y; + } + + public double getX() { + return x; + } + + public double getY() { + return y; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2404/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2404/Solution.java new file mode 100644 index 0000000..01ab761 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2404/Solution.java @@ -0,0 +1,61 @@ +package com.javarush.task.task24.task2404; + +import com.javarush.task.task24.task2404.HasHeight; +import com.javarush.task.task24.task2404.HasWidth; +import com.javarush.task.task24.task2404.Point; + +/* +Рефакторинг Rectangle +*/ +public class Solution { + public static void main(String[] args) { + Rectangle rectangle = new Rectangle(1, 2, 3, 4); + //System.out.println(getHeight(rectangle)); + //System.out.println(getWidth(rectangle)); + /////////////////////expected////////////////// + System.out.println(getHeight(rectangle.castToHasHeight())); + System.out.println(getWidth(rectangle.castToHasWidth())); + } + + public static double getHeight(HasHeight rectangle) { + return rectangle.getHeight(); + } + + public static double getWidth(HasWidth rectangle) { + return rectangle.getWidth(); + } + + + public static class Rectangle { + private Point point1; + private Point point2; + + public Rectangle(double x1, double y1, double x2, double y2) { + point1 = new Point(x1, y1); + point2 = new Point(x2, y2); + } + + + public HasHeight castToHasHeight() { + class Height implements HasHeight{ + + @Override + public double getHeight() { + return Math.abs(point1.getY() - point2.getY()); + } + } + return new Height(); + } + + public HasWidth castToHasWidth() { + class Width implements HasWidth { + + @Override + public double getWidth() { + return Math.abs(point1.getX() - point2.getX()); + } + } + return new Width(); + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task24/task2404/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task24/task2404/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..506b195 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task24/task2404/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,13 @@ +taskKey="com.javarush.task.task24.task2404" + +Рефакторинг Rectangle + +В классе Rectangle: +1. Измени методы getHeight и getWidth, чтобы они возвращали объекты типов HasHeight и HasWidth соответственно. +2. Для этого внутри методов getHeight и getWidth создай локальные классы - реализации интерфейсов. +3. Переименуй getHeight в castToHasHeight, getWidth в castToHasWidth (на имени метода нажми Shift+F6). +4. Убери наследование интерфейсов в классе Rectangle. + +P.S. Ожидается, что после внесения требуемых изменений, закомментированный код в методе станет рабочим и должен быть раскомментирован. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2405/Action.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2405/Action.java new file mode 100644 index 0000000..e2d75ad --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2405/Action.java @@ -0,0 +1,5 @@ +package com.javarush.task.task24.task2405; + +public interface Action { + void someAction(); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2405/FirstClass.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2405/FirstClass.java new file mode 100644 index 0000000..42a5668 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2405/FirstClass.java @@ -0,0 +1,14 @@ +package com.javarush.task.task24.task2405; + +public abstract class FirstClass implements Action { //first implementation + + protected FirstClass() { + Solution.countActionObjects++; + } + + public void someAction() { + System.out.println("class FirstClass, method someAction"); + } + + public abstract Action getDependantAction(); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2405/SecondClass.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2405/SecondClass.java new file mode 100644 index 0000000..6d678dc --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2405/SecondClass.java @@ -0,0 +1,16 @@ +package com.javarush.task.task24.task2405; + +public class SecondClass implements Action { //second implementation + public static String SPECIFIC_ACTION_FOR_ANONYMOUS_SECOND_CLASS_PARAM = "\nSpecific action for anonymous SecondClass, param = "; + + private static String SECOND_CLASS_METHOD_STRING = "class SecondClass, method someAction"; + + public SecondClass() { + Solution.countActionObjects++; + } + protected StringBuilder sb = new StringBuilder(SECOND_CLASS_METHOD_STRING); + + public void someAction() { + System.out.println(sb.toString()); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2405/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2405/Solution.java new file mode 100644 index 0000000..feca245 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2405/Solution.java @@ -0,0 +1,79 @@ +package com.javarush.task.task24.task2405; + +/* +Black box +*/ +public class Solution implements Action { + public static int countActionObjects; + + private int param; + + private Action solutionAction = new Action() { + + //!!!!! Changes can be here + //!!!!! Изменения могут быть тут + class ThirdClass extends SecondClass{ + public void someAction() { + super.someAction(); + System.out.print(SPECIFIC_ACTION_FOR_ANONYMOUS_SECOND_CLASS_PARAM.substring(1) + param + "\n"); + } + } + + public void someAction() { + //!!!!! All changes have to be here + //!!!!! Все изменения должны быть только тут + + while (param > 0) { + System.out.println(param); + param--; + } + if (param == 0) { + new FirstClass(){ + + @Override + public Action getDependantAction() { + return null; + } + }.someAction(); + } + if (param <= 0) { + new SecondClass().someAction(); + System.out.print(SecondClass.SPECIFIC_ACTION_FOR_ANONYMOUS_SECOND_CLASS_PARAM.substring(1) + param + "\n"); + } + } + }; + + + public Solution(int param) { + this.param = param; + } + + @Override + public void someAction() { + solutionAction.someAction(); + } + + /** + * 5 + * 4 + * 3 + * 2 + * 1 + * class FirstClass, method someAction + * class SecondClass, method someAction + * Specific action for anonymous SecondClass, param = 0 + * Count of created Action objects is 2 + * class SecondClass, method someAction + * Specific action for anonymous SecondClass, param = -1 + * Count of created Action objects is 3 + */ + public static void main(String[] args) { + Solution solution = new Solution(5); + solution.someAction(); + System.out.println("Count of created Action objects is " + countActionObjects); + + solution = new Solution(-1); + solution.someAction(); + System.out.println("Count of created Action objects is " + countActionObjects); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task24/task2405/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task24/task2405/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..037a4ca --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task24/task2405/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,12 @@ +taskKey="com.javarush.task.task24.task2405" + +Black box + +1. Восстанови логику метода someAction для поля solutionAction. +2. Пример вывода смотри в комментарии к методу main. +3. Подсказка: метод someAction анонимного класса поля solutionAction должен вызвать метод сабкласса FirstClass, +если param > 0, иначе вызвать метод сабкласса SecondClass. + +Не изменяй метод main! + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2406/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2406/Solution.java new file mode 100644 index 0000000..2bfa72d --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2406/Solution.java @@ -0,0 +1,37 @@ +package com.javarush.task.task24.task2406; + +import java.math.BigDecimal; + +/* +Наследование от внутреннего класса +*/ +public class Solution { + public class Building { + public class Hall { + private BigDecimal square; + + public Hall(BigDecimal square) { + this.square = square; + } + } + + public class Apartments { + } + } + + public class Apt3Bedroom extends Building.Apartments{ + public Apt3Bedroom(Building building){ + building.super(); + } + } + + public class BigHall extends Solution.Building.Hall{ + public BigHall(Solution.Building building){ + building.super(new BigDecimal("323")); + } + } + + public static void main(String[] args) { + + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task24/task2406/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task24/task2406/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..5f0e7f4 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task24/task2406/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,8 @@ +taskKey="com.javarush.task.task24.task2406" + +Наследование от внутреннего класса + +Внутри класса Solution создай 2 внутренних public класса Apt3Bedroom, BigHall. +Унаследуй их от Apartments и Hall. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Cat.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Cat.java new file mode 100644 index 0000000..f8cde3f --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Cat.java @@ -0,0 +1,48 @@ +package com.javarush.task.task24.task2407; + +/* +В работе вам иногда будет нужно закастить класс к какому-нибудь интерфейсу (тут Sayable), +который не реализован в текущем классе + */ +public class Cat implements Pet { + private String name; + + public Cat(String name) { + this.name = name; + } + + /** + * Это - механизм адаптирования к другому интерфейсу - Sayable + * Внутри метода toSayable создайте class CatPet, реализующий интерфейс Sayable + * Логика метода say: + * Если i <= 0, то вывести на экран, что кот спит. Пример, "Васька спит."' + * Иначе вывести фразу: "имя_кота говорит мяу!". Пример для i=3, "Васька говорит мяяяу!" + *

+ * Пример вывода: + * Мурзик спит. + * Васька говорит мяяу! + * Кошка говорит мяяяяяу! + * Мышь пищит. + * Томас говорит мяу! + *

+ * @param i количество букв 'я' в слове мяу + * @return экземпляр класса CatPet + */ + public Sayable toSayable(final int i) { + class CatPet implements Sayable{ + + @Override + public String say() { + if (i <= 0) return name + " спит."; + else { + StringBuilder str = new StringBuilder(); + for (int j = 0; j < i; j++){ + str.append("я"); + } + return name + " говорит м" + str + "у!"; + } + } + } + return new CatPet(); + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Mouse.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Mouse.java new file mode 100644 index 0000000..b5ff3fe --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Mouse.java @@ -0,0 +1,17 @@ +package com.javarush.task.task24.task2407; + +/* +обратите внимание, как именно Mouse отличается от Cat +Этот класс - привычный для вас. +*/ +public class Mouse implements Pet, Sayable { + @Override + public Sayable toSayable(int i) { + return this; + } + + @Override + public String say() { + return "Мышь пищит."; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Pet.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Pet.java new file mode 100644 index 0000000..d4c8f78 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Pet.java @@ -0,0 +1,5 @@ +package com.javarush.task.task24.task2407; + +public interface Pet { + public Sayable toSayable(int i); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Sayable.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Sayable.java new file mode 100644 index 0000000..aaea511 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Sayable.java @@ -0,0 +1,5 @@ +package com.javarush.task.task24.task2407; + +public interface Sayable { + String say(); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Solution.java new file mode 100644 index 0000000..4e76c0d --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Solution.java @@ -0,0 +1,14 @@ +package com.javarush.task.task24.task2407; + +import java.util.List; + +/* +Реализация интерфейса используя локальный класс +*/ +public class Solution { + public static void main(String[] args) { + List pet = Util.getPets(); + List pets = Util.convertPetToSayable(pet); + Util.printDialog(pets); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Util.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Util.java new file mode 100644 index 0000000..33b1603 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2407/Util.java @@ -0,0 +1,32 @@ +package com.javarush.task.task24.task2407; + +import java.util.LinkedList; +import java.util.List; + +public class Util { + //Util отлично работает со всеми классами Cat, Mouse. А ведь Mouse отличается от Cat. + public static void printDialog(List pets) { + for (int i = 0; i < pets.size(); i++) { + System.out.println(pets.get(i).say()); + } + } + + public static List getPets() { + List pets = new LinkedList<>(); + pets.add(new Cat("Мурзик")); + pets.add(new Cat("Васька")); + pets.add(new Cat("Кошка")); + pets.add(new Mouse()); + pets.add(new Cat("Томас")); + return pets; + } + + public static List convertPetToSayable(List pets) { + List result = new LinkedList<>(); + for (Pet pet : pets) { + int i = (int) (Math.random() * 7) - 2; + result.add(pet.toSayable(i)); + } + return result; + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task24/task2407/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task24/task2407/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..480215e --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task24/task2407/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,7 @@ +taskKey="com.javarush.task.task24.task2407" + +Реализация интерфейса используя локальный класс + +В классе Cat реализуй логику метода toSayable, которая описана в джавадоке. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Dog.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Dog.java new file mode 100644 index 0000000..2380df3 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Dog.java @@ -0,0 +1,66 @@ +package com.javarush.task.task24.task2408; + +import java.util.Date; + +/* +В работе вам иногда будет нужно закастить класс к какому-нибудь другому классу, не интерфейсу :))) +Класс DogPet использует 2 класса - SuperDog и Dog, разберись с getName в классе DogPet +Так намного лучше, чем Copy+Paste! + */ +public class Dog implements Pet { + private String name; + + public Dog(String name) { + this.name = name; + } + + /** + * Если так получилось, что есть готовый класс А (тут SuperDog) с логикой, которую вы хотите использовать. + * То возможны 3 способа: + * 1) из класса А скопировать логику себе (это плохо, т.к. поддерживать несколько копий одного и того же кода проблематично) + * 2) создать экземпляр класса А внутри нашего класса и использовать его, связь has-a (не всегда подходит, т.к. класс А сам по себе) + * 3) создать внутренний класс, который наследуется от А, использовать его методы вместе с + * методами и полями нашего класса, т.к. внутренний класс имеет доступ к своему родителю как наследник, + * а также ко всем полям и методам включая private того класса, в который он вложен. + *

+ * Итак, разбираемся с п.3: + * Внутри метода toSayable создайте class DogPet, который наследуется от SuperDog и реализует интерфейс Sayable + * создайте метод private String getName(), который будет использовать логику двух классов - Dog и SuperDog. + * Пусть этот метод возвращает имя собаки (класс Dog), которое с обеих сторон выделено getSuperQuotes (класс SuperDog) + * Пример, " *** Барбос *** " + * Логика метода say: + * Если i < 1, то используя метод getName вывести на экран, что собака спит. Пример, " *** Шарик *** спит."' + * Иначе вывести фразу: "имя_собаки лает гааав! сегодняшняя_дата". Пример для i=3, " *** Тузик *** лает гааав! 13-ноя-2013 Ср" + * Для форматирования даты используйте formatter из класса SuperDog. + *

+ * Пример вывода: + * *** Барбос *** лает гааааав! 13-ноя-2013 Ср + * *** Тузик *** лает гаав! 13-ноя-2013 Ср + * *** Бобик *** лает гааав! 13-ноя-2013 Ср + * Мыша пищит. + * *** Шарик *** спит. + * + * @param i количество букв 'а' в слове гав + * @return экземпляр класса DogPet + */ + public Sayable toSayable(final int i) { + class DogPet extends SuperDog implements Sayable{ + + private String getName(){ + return getSuperQuotes() + name + getSuperQuotes(); + } + @Override + public String say() { + if ( i < 1 ) { return getName() + " спит."; } + else { + StringBuilder str = new StringBuilder(); + for (int j = 0; j < i; j++) { + str.append("а"); + } + return getName() + " лает г" + str + "в! " + formatter.format(new Date()); + } + } + } + return new DogPet(); + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Mouse.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Mouse.java new file mode 100644 index 0000000..1792006 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Mouse.java @@ -0,0 +1,17 @@ +package com.javarush.task.task24.task2408; + +/* +обратите внимание, как именно Mouse отличается от Dog +Этот класс - привычный для вас. +*/ +public class Mouse implements Pet, Sayable { + @Override + public Sayable toSayable(int i) { + return this; + } + + @Override + public String say() { + return "Мышь пищит."; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Pet.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Pet.java new file mode 100644 index 0000000..37bf044 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Pet.java @@ -0,0 +1,5 @@ +package com.javarush.task.task24.task2408; + +public interface Pet { + public Sayable toSayable(int i); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Sayable.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Sayable.java new file mode 100644 index 0000000..33c75aa --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Sayable.java @@ -0,0 +1,5 @@ +package com.javarush.task.task24.task2408; + +public interface Sayable { + String say(); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Solution.java new file mode 100644 index 0000000..a909467 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Solution.java @@ -0,0 +1,14 @@ +package com.javarush.task.task24.task2408; + +import java.util.List; + +/* +Как избежать Copy+Paste +*/ +public class Solution { + public static void main(String[] args) { + List pet = Util.getPets(); + List pets = Util.convertPetToSayable(pet); + Util.printDialog(pets); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2408/SuperDog.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/SuperDog.java new file mode 100644 index 0000000..ad29824 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/SuperDog.java @@ -0,0 +1,12 @@ +package com.javarush.task.task24.task2408; + +import java.text.SimpleDateFormat; + +public abstract class SuperDog { + protected String getSuperQuotes() { + //some logic here + return " *** "; + } + + protected SimpleDateFormat formatter = new SimpleDateFormat("dd-MMM-yyyy EEE"); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Util.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Util.java new file mode 100644 index 0000000..fd12c12 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/Util.java @@ -0,0 +1,32 @@ +package com.javarush.task.task24.task2408; + +import java.util.LinkedList; +import java.util.List; + +public class Util { + //Util отлично работает с классами Dog, Mouse. + public static void printDialog(List pets) { + for (int i = 0; i < pets.size(); i++) { + System.out.println(pets.get(i).say()); + } + } + + public static List getPets() { + List pets = new LinkedList<>(); + pets.add(new Dog("Барбос")); + pets.add(new Dog("Тузик")); + pets.add(new Dog("Бобик")); + pets.add(new Mouse()); + pets.add(new Dog("Шарик")); + return pets; + } + + public static List convertPetToSayable(List pets) { + List result = new LinkedList<>(); + for (Pet pet : pets) { + int i = (int) (Math.random() * 7) - 2; + result.add(pet.toSayable(i)); + } + return result; + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task24/task2408/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..b7fa41f --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task24/task2408/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,7 @@ +taskKey="com.javarush.task.task24.task2408" + +Как избежать Copy+Paste + +В классе Dog реализуй логику метода toSayable, которая описана в джавадоке. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2409/Item.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2409/Item.java new file mode 100644 index 0000000..1c8934c --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2409/Item.java @@ -0,0 +1,10 @@ +package com.javarush.task.task24.task2409; + +/** + * Created by PAKOT on 09.03.2017. + */ +public interface Item { + public int getId(); + public double getPrice(); + public String getTM(); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2409/Jeans.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2409/Jeans.java new file mode 100644 index 0000000..274644b --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2409/Jeans.java @@ -0,0 +1,9 @@ +package com.javarush.task.task24.task2409; + +/** + * Created by PAKOT on 09.03.2017. + */ +public interface Jeans extends Item { + public int getLength(); + public int getSize(); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2409/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2409/Solution.java new file mode 100644 index 0000000..ab9b9bc --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2409/Solution.java @@ -0,0 +1,18 @@ +package com.javarush.task.task24.task2409; + +import java.util.List; + +/* +Интернет-магазин продажи джинсов +*/ +public class Solution { + + public static List allJeans = Util.getAllJeans(); + + public static void main(String[] args) { + for (Jeans jeans : allJeans) { + System.out.println(jeans); + } + } + +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2409/Util.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2409/Util.java new file mode 100644 index 0000000..7e01fae --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2409/Util.java @@ -0,0 +1,128 @@ +package com.javarush.task.task24.task2409; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +public class Util { + protected static Collection jeansArray = new LinkedList<>(); + + static { + jeansArray.add(new Object[]{1, Company.Levis, 34, 6, 150.0}); + jeansArray.add(new Object[]{2, Company.Denim, 35, 8, 154.0}); + jeansArray.add(new Object[]{3, Company.Colins, 32, 6, 120.0}); + jeansArray.add(new Object[]{4, Company.CalvinKleinJeans, 31, 8, 125.0}); + } + + public static List getAllJeans() { + + //add your code here + abstract class AbstractJeans implements Jeans{ + protected int id; + protected int length; + protected int size; + protected double price; + + + public AbstractJeans(int id, int length, int size, double price){ + this.id = id; + this.length = length; + this.size = size; + this.price = price; + } + + public int getSize(){ + return size; + } + + public double getPrice(){ + return price; + } + + public int getId(){ + return id; + } + + public int getLength(){ + return length; + } + + @Override + public String toString() { + return this.getClass().getSimpleName() + "{" + + "id=" + id + + ", length=" + length + + ", size=" + size + + ", price=" + price + + '}'; + } + } + + class Levis extends AbstractJeans{ + + public Levis(int id, int length, int size, double price){ + super(id, length, size, price); + + } + @Override + public String getTM() { + return Company.Levis.fullName; + } + } + + class Denim extends AbstractJeans{ + public Denim(int id, int length, int size, double price){ + super(id, length, size, price); + + } + @Override + public String getTM() { + return Company.Denim.name(); + } + } + + List allJeans = new LinkedList<>(); + + for (Object[] obj : getJeansArray()) { + int id = (int) obj[0]; + final Company company = (Company ) obj[1]; + int length = (int) obj[2]; + int size = (int) obj[3]; + double price = (double) obj[4]; + + Jeans jeans = null; + if (Company.Levis == company) { + jeans = new Levis(id, length, size, price); + } else + if (Company.Denim == company) { + jeans = new Denim(id, length, size, price); + } else { + jeans = new AbstractJeans(id, length, size, price) { + public String getTM() { + return company.fullName; + } + }; + } + allJeans.add(jeans); + } + return allJeans; + } + + + + public static Collection getJeansArray() { + return jeansArray; + } + + static enum Company { + Levis ("Levi's"), + Denim("Denim"), + Colins("COLIN'S"), + CalvinKleinJeans("Calvin Klein Jeans"); + + final String fullName; + Company(String name) { + this.fullName = name; + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task24/task2409/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task24/task2409/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..ce5736c --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task24/task2409/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,16 @@ +taskKey="com.javarush.task.task24.task2409" + +Интернет-магазин продажи джинсов + +1. Создай 2 интерфейса в отдельных файлах: +1.1) Item с методами int getId(), double getPrice(), String getTM() +1.2) Jeans extends Item с методами int getLength() и int getSize() + +2. В классе Util в методе getAllJeans добавь пропущенную часть java-кода: +2.1) разберись в том, что уже есть в методе getAllJeans класса Util +2.2) создай абстрактный class AbstractJeans от интерфейса Jeans с одним абстрактным методом, реализуй остальные методы +2.3) создай классы Levis и Denim от AbstractJeans, реализуй оставшийся метод +2.4) в классе AbstractJeans реализуй метод toString() (можешь воспользоваться Alt+Insert -> toString()) +2.5) метод toString класса AbstractJeans должен начинаться с имени сабкласса, например, Levis{id=1, length=34, size=6, price=150.0} + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2410/Iterator.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2410/Iterator.java new file mode 100644 index 0000000..048d0e1 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2410/Iterator.java @@ -0,0 +1,5 @@ +package com.javarush.task.task24.task2410; + +public interface Iterator { + Iterator next(); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2410/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2410/Solution.java new file mode 100644 index 0000000..4b150d4 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2410/Solution.java @@ -0,0 +1,48 @@ +package com.javarush.task.task24.task2410; + +import java.util.LinkedList; +import java.util.List; + +/* +Рефакторинг, анонимные классы +*/ +public class Solution { + public static List iterators = new LinkedList<>(); + + private int countItems; + + public Iterator getIterator(final String name) { + return new Iterator() { + { + countItems++; + System.out.println(name + " item " + countItems); + } + + @Override + public Iterator next() { + return getIterator(name); + } + }; + + /*class LocalIterator implements Iterator { + public LocalIterator() { + countItems++; + System.out.println(name + " item " + countItems); + } + + public Iterator next() { + return new LocalIterator(); + } + } + return new LocalIterator();*/ + } + + public static void main(String[] args) { + Solution solution = new Solution(); + + Iterator iterator = solution.getIterator("iterator"); + for (int i = 1; i < 5; i++) { + iterators.add(iterator.next()); + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task24/task2410/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task24/task2410/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..bda2251 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task24/task2410/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,9 @@ +taskKey="com.javarush.task.task24.task2410" + +Рефакторинг, анонимные классы + +Сделайте так, чтобы метод getIterator возвращал анонимный класс. +Перенесите логику LocalIterator в анонимный класс. +Меняйте только тело метода getIterator. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2411/C.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2411/C.java new file mode 100644 index 0000000..51b0fa6 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2411/C.java @@ -0,0 +1,8 @@ +package com.javarush.task.task24.task2411; + +public class C implements JustAnInterface { + public C() { + System.out.print("C"); + B localB = B; + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2411/JustAnInterface.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2411/JustAnInterface.java new file mode 100644 index 0000000..01492c7 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2411/JustAnInterface.java @@ -0,0 +1,11 @@ +package com.javarush.task.task24.task2411; + +public interface JustAnInterface { + public static final B B = new B(); + + class B extends C { + public B() { + System.out.print("B"); + } + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2411/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2411/Solution.java new file mode 100644 index 0000000..da43bde --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2411/Solution.java @@ -0,0 +1,34 @@ +package com.javarush.task.task24.task2411; + +/* +Вспомним наследование +*/ +public class Solution extends C { + private class A { + protected String value = "A"; + + public A() { + System.out.print(value); + } + } + + private A a = new A() { + { //у анонимных классов нет своих конструкторов, но что-то можно сделать в блоке инициализации класса + value = "Y"; + if (super.getClass().getName().contains(".Solution$")) { + System.out.print(value); + } + } + }; + + public Solution() { + System.out.print("S"); + } + + public static void main(String[] args) { + new Solution(); + } +} + + + diff --git "a/3.JavaMultithreading/src/com/javarush/task/task24/task2411/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task24/task2411/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..210c287 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task24/task2411/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,7 @@ +taskKey="com.javarush.task.task24.task2411" + +Вспомним наследование + +Исправить наследование во всех классах, чтобы вывод метода main был CCBAYS. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2412/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2412/Solution.java new file mode 100644 index 0000000..ec32daf --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2412/Solution.java @@ -0,0 +1,135 @@ +package com.javarush.task.task24.task2412; + +import java.text.ChoiceFormat; +import java.text.Format; +import java.text.MessageFormat; +import java.text.SimpleDateFormat; +import java.util.*; + +/* +Знания - сила! +*/ +public class Solution { + public static void main(String[] args) { + List stocks = getStocks(); + sort(stocks); + Date actualDate = new Date(); + printStocks(stocks, actualDate); + } + + public static void printStocks(List stocks, Date actualDate) { + SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy"); + + double[] filelimits = {0d, actualDate.getTime()}; + String[] filepart = {"closed {4}", "open {2} and last {3}"}; + + ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart); + Format[] testFormats = {null, null, dateFormat, fileform}; + MessageFormat pattform = new MessageFormat("{0} {1} | {5} {6}"); + pattform.setFormats(testFormats); + + for (Stock stock : stocks) { + String name = ((String) stock.get("name")); + String symbol = (String) stock.get("symbol"); + double open = !stock.containsKey("open") ? 0 : ((double) stock.get("open")); + double last = !stock.containsKey("last") ? 0 : ((double) stock.get("last")); + double change = !stock.containsKey("change") ? 0 : ((double) stock.get("change")); + Date date = (Date) stock.get("date"); + Object[] testArgs = {name, symbol, open, last, change, date, date.getTime()}; + System.out.println(pattform.format(testArgs)); + } + } + + + public static void sort(List list) { + + + Collections.sort(list, new Comparator() { + @Override + public int compare(Stock stock1, Stock stock2) { + int result = ((String) stock1.get("name")).compareTo( ((String) stock2.get("name"))); + if (result != 0) { return result; } + else{ + Date o1Date = (Date) stock1.get("date"); + Date o2Date = (Date) stock2.get("date"); + o1Date.setHours(0); + o1Date.setMinutes(0); + o1Date.setSeconds(0); + o2Date.setHours(0); + o2Date.setMinutes(0); + o2Date.setSeconds(0); + result = o2Date.compareTo(o1Date); + if (result != 0) { return result; } + else { + double stock1Change; + double stock2Change; + if (stock1.containsKey("change")) { + stock1Change = (double) stock1.get("change"); + } else { + stock1Change = (double) stock1.get("last") - (double) stock1.get("open"); + } + if (stock2.containsKey("change")) { + stock2Change = (double) stock2.get("change"); + } else { + stock2Change = (double) stock2.get("last") - (double) stock2.get("open"); + } + return Double.compare(stock2Change, stock1Change); + } + } + + } + }); + + } + + public static class Stock extends HashMap { + public Stock(String name, String symbol, double open, double last) { + put("name", name); + put("symbol", symbol); + put("open", open); + put("last", last); + put("date", getRandomDate(2020)); + } + + public Stock(String name, String symbol, double change, Date date) { + put("name", name); + put("symbol", symbol); + put("date", date); + put("change", change); + } + } + + public static List getStocks() { + List stocks = new ArrayList(); + + stocks.add(new Stock("Fake Apple Inc.", "AAPL", 125.64, 123.43)); + stocks.add(new Stock("Fake Cisco Systems, Inc.", "CSCO", 25.84, 26.3)); + stocks.add(new Stock("Fake Google Inc.", "GOOG", 516.2, 512.6)); + stocks.add(new Stock("Fake Intel Corporation", "INTC", 21.36, 21.53)); + stocks.add(new Stock("Fake Level 3 Communications, Inc.", "LVLT", 5.55, 5.54)); + stocks.add(new Stock("Fake Microsoft Corporation", "MSFT", 29.56, 29.72)); + + stocks.add(new Stock("Fake Nokia Corporation (ADR)", "NOK", .1, getRandomDate())); + stocks.add(new Stock("Fake Oracle Corporation", "ORCL", .15, getRandomDate())); + stocks.add(new Stock("Fake Starbucks Corporation", "SBUX", .03, getRandomDate())); + stocks.add(new Stock("Fake Yahoo! Inc.", "YHOO", .32, getRandomDate())); + stocks.add(new Stock("Fake Applied Materials, Inc.", "AMAT", .26, getRandomDate())); + stocks.add(new Stock("Fake Comcast Corporation", "CMCSA", .5, getRandomDate())); + stocks.add(new Stock("Fake Sirius Satellite", "SIRI", -.03, getRandomDate())); + + return stocks; + } + + public static Date getRandomDate() { + return getRandomDate(1970); + } + + public static Date getRandomDate(int startYear) { + int year = startYear + (int) (Math.random() * 30); + int month = (int) (Math.random() * 12); + int day = (int) (Math.random() * 28); + GregorianCalendar calendar = new GregorianCalendar(year, month, day); + return calendar.getTime(); + } +} + diff --git "a/3.JavaMultithreading/src/com/javarush/task/task24/task2412/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task24/task2412/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..ef7ae27 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task24/task2412/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,15 @@ +taskKey="com.javarush.task.task24.task2412" + +Знания - сила! + +1. В методе sort написать компаратор для Stock: +1.1. Первичная сортировка по name в алфавитном порядке +1.2. Вторичная сортировка по дате без учета часов, минут, секунд (сверху самые новые), потом по прибыли от положительных к отрицательным +... open 125,64 and last 126,74 - тут прибыль = 126,74-125,64 +... open 125,64 and last 123,43 - тут прибыль = 123,43-125,64 +2. Разобраться с *Format-ами и исправить IllegalArgumentException. Подсказка - это одна строчка. +Пример вывода: +Fake Apple Inc. AAPL | 17-11-2025 open 125,64 and last 123,43 +Fake Oracle Corporation ORCL | 21-08-1989 closed 0,15 + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Arkanoid.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Arkanoid.java new file mode 100644 index 0000000..d458ccf --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Arkanoid.java @@ -0,0 +1,238 @@ +package com.javarush.task.task24.task2413; + +import java.awt.event.KeyEvent; +import java.util.ArrayList; + +/** + * Главный класс игры + */ +public class Arkanoid { + //ширина и высота + private int width; + private int height; + + //список кирпичей + private ArrayList bricks = new ArrayList(); + //шарик + private Ball ball; + //подставка + private Stand stand; + + //игра закончена? + private boolean isGameOver = false; + + public Arkanoid(int width, int height) { + this.width = width; + this.height = height; + } + + public ArrayList getBricks() { + return bricks; + } + + public Ball getBall() { + return ball; + } + + public void setBall(Ball ball) { + this.ball = ball; + } + + public Stand getStand() { + return stand; + } + + public void setStand(Stand stand) { + this.stand = stand; + } + + /** + * Рисуем на холсте границы и все объекты. + */ + void draw(Canvas canvas) { + drawBorders(canvas); + + //draw bricks + for (Brick brick : bricks) { + brick.draw(canvas); + } + + //draw ball + ball.draw(canvas); + + //draw stand + stand.draw(canvas); + + } + + /** + * Рисуем на холсте границы + */ + private void drawBorders(Canvas canvas) { + //draw game + for (int i = 0; i < width + 2; i++) { + for (int j = 0; j < height + 2; j++) { + canvas.setPoint(i, j, '.'); + } + } + + for (int i = 0; i < width + 2; i++) { + canvas.setPoint(i, 0, '-'); + canvas.setPoint(i, height + 1, '-'); + } + + for (int i = 0; i < height + 2; i++) { + canvas.setPoint(0, i, '|'); + canvas.setPoint(width + 1, i, '|'); + } + } + + /** + * Основной цикл программы. + * Тут происходят все важные действия + */ + void run() throws Exception { + //Создаем холст для отрисовки. + Canvas canvas = new Canvas(width, height); + + //Создаем объект "наблюдатель за клавиатурой" и стартуем его. + KeyboardObserver keyboardObserver = new KeyboardObserver(); + keyboardObserver.start(); + + //Исполняем цикл, пока игра не окончека + while (!isGameOver) { + //"наблюдатель" содержит события о нажатии клавиш? + if (keyboardObserver.hasKeyEvents()) { + KeyEvent event = keyboardObserver.getEventFromTop(); + + //Если "стрелка влево" - сдвинуть фигурку влево + if (event.getKeyCode() == KeyEvent.VK_LEFT) + stand.moveLeft(); + //Если "стрелка вправо" - сдвинуть фигурку вправо + else if (event.getKeyCode() == KeyEvent.VK_RIGHT) + stand.moveRight(); + //Если "пробел" - запускаем шарик + else if (event.getKeyCode() == KeyEvent.VK_SPACE) + ball.start(); + } + + //двигаем все объекты + move(); + + //проверяем столкновения + checkBricksBump(); + checkStandBump(); + + //проверяем, что шарик мог улететь через дно. + checkEndGame(); + + //отрисовываем все объекты + canvas.clear(); + draw(canvas); + canvas.print(); + + //пауза + Thread.sleep(300); + } + + //Выводим сообщение "Game Over" + System.out.println("Game Over!"); + } + + /** + * Двигаем шарик и подставку. + */ + public void move() { + ball.move(); + stand.move(); + } + + /** + * Проверяем столкновение с кирпичами. + * Если столкновение было - шарик отлетает в случайном направлении 0..360 градусов + */ + void checkBricksBump() { + for (Brick brick : new ArrayList(bricks)) { + if (ball.isIntersec(brick)) { + double angle = Math.random() * 360; + ball.setDirection(angle); + + bricks.remove(brick); + } + } + } + + /** + * Проверяем столкновение с подставкой. + * Если столкновение было - шарик отлетает в случайном направлении вверх 80..100 градусов. + */ + void checkStandBump() { + if (ball.isIntersec(stand)) { + double angle = 90 + 20 * (Math.random() - 0.5); + ball.setDirection(angle); + } + } + + /** + * Проверяем - не улетел ли шарик через дно. + * Если да - игра окончена (isGameOver = true) + */ + void checkEndGame() { + if (ball.getY() > height && ball.getDy() > 0) + isGameOver = true; + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public void setWidth(int width) { + this.width = width; + } + + public void setHeight(int height) { + this.height = height; + } + + public static Arkanoid game; + + public static void main(String[] args) throws Exception { + game = new Arkanoid(20, 30); + + Ball ball = new Ball(10, 29, 2, 95); + game.setBall(ball); + + Stand stand = new Stand(10, 30); + game.setStand(stand); + + game.getBricks().add(new Brick(3, 3)); + game.getBricks().add(new Brick(7, 5)); + game.getBricks().add(new Brick(12, 5)); + game.getBricks().add(new Brick(16, 3)); + + game.run(); + } +} + + + + + + + + + + + + + + + + + + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Ball.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Ball.java new file mode 100644 index 0000000..c9d1640 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Ball.java @@ -0,0 +1,116 @@ +package com.javarush.task.task24.task2413; + +/** + * Класс для шарика в игре + */ +public class Ball extends BaseObject { + //скорость + private double speed; + //направление (в градусах от 0 до 360) + private double direction; + + //текущее значение вектора движения (dx,dy) + private double dx; + private double dy; + + //заморожен ли объект или может двигаться + private boolean isFrozen; + + public Ball(double x, double y, double speed, double direction) { + super(x, y, 1); + + this.direction = direction; + this.speed = speed; + + this.isFrozen = true; + } + + public double getSpeed() { + return speed; + } + + public void setSpeed(double speed) { + this.speed = speed; + } + + public double getDirection() { + return direction; + } + + public double getDx() { + return dx; + } + + public double getDy() { + return dy; + } + + /** + * Устанавливаем новое направление движения. + * Тут же вычисляем и новый вектор. + * Такой подход удобно использовать при отскоках от стен. + */ + void setDirection(double direction) { + this.direction = direction; + + double angel = Math.toRadians(direction); + dx = Math.cos(angel) * speed; + dy = -Math.sin(angel) * speed; + } + + /** + * Рисуем себя на "канвасе". + */ + @Override + void draw(Canvas canvas) { + canvas.setPoint(x, y, 'O'); + } + + /** + * Двигаем себя на один шаг. + */ + public void move() { + if (isFrozen) return; + + x += dx; + y += dy; + + checkRebound(1, Arkanoid.game.getWidth(), 1, Arkanoid.game.getHeight() + 5); + } + + /** + * Проверяем не улетел ли шарик за стенку. + * Если да - отражаем его. + */ + void checkRebound(int minx, int maxx, int miny, int maxy) { + if (x < minx) { + x = minx + (minx - x); + dx = -dx; + } + + if (x > maxx) { + x = maxx - (x - maxx); + dx = -dx; + } + + if (y < miny) { + y = miny + (miny - y); + dy = -dy; + } + + if (y > maxy) { + y = maxy - (y - maxy); + dy = -dy; + } + } + + /** + * Запускам шарик. + * isFrozen = false. + * Пересчитываем вектор движения (dx,dy). + */ + void start() { + this.setDirection(direction); + this.isFrozen = false; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2413/BaseObject.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/BaseObject.java new file mode 100644 index 0000000..702d196 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/BaseObject.java @@ -0,0 +1,73 @@ +package com.javarush.task.task24.task2413; + +/** + * Базовый класс для всех объектов игры. + */ +public abstract class BaseObject { + //координаты + protected double x; + protected double y; + //радиус объекта + protected double radius; + + protected BaseObject(double x, double y, double radius) { + this.x = x; + this.y = y; + this.radius = radius; + } + + public double getX() { + return x; + } + + public void setX(double x) { + this.x = x; + } + + public double getY() { + return y; + } + + public void setY(double y) { + this.y = y; + } + + public double getRadius() { + return radius; + } + + public void setRadius(double radius) { + this.radius = radius; + } + + /** + * Метод рисует свой объект на "канвасе". + */ + abstract void draw(Canvas canvas); + + /** + * Двигаем себя на один ход. + */ + abstract void move(); + + /** + * Проверяем - не выходит ли (x,y) за границы. + */ + void checkBorders(double minx, double maxx, double miny, double maxy) { + if (x < minx) x = minx; + if (x > maxx) x = maxx; + if (y < miny) y = miny; + if (y > maxy) y = maxy; + } + + /** + * Проверяем - пересекаются ли переданный(o) и наш(this) объекты. + */ + boolean isIntersec(BaseObject o) { + double dx = x - o.x; + double dy = y - o.y; + double destination = Math.sqrt(dx * dx + dy * dy); + double destination2 = Math.max(radius, o.radius); + return destination <= destination2; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Brick.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Brick.java new file mode 100644 index 0000000..cf5aa72 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Brick.java @@ -0,0 +1,35 @@ +package com.javarush.task.task24.task2413; + +/** + * Класс для объекта "кирпич". + */ +public class Brick extends BaseObject { + //картинка для отрисовки + private static int[][] matrix = { + {0, 0, 0, 0, 0}, + {0, 1, 1, 1, 0}, + {0, 1, 1, 1, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }; + + public Brick(double x, double y) { + super(x, y, 3); + } + + /** + * Рисуем себя на холсте + */ + @Override + void draw(Canvas canvas) { + canvas.drawMatrix(x - radius + 1, y, matrix, 'H'); + } + + /** + * Ничего не делаем - кирпич неподвижен + */ + @Override + void move() { + //do nothing + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Canvas.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Canvas.java new file mode 100644 index 0000000..92bd8c4 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Canvas.java @@ -0,0 +1,86 @@ +package com.javarush.task.task24.task2413; + +/** + * Класс-холст для отрисовки. + */ +public class Canvas { + //ширина и высота + private int width; + private int height; + //матрица, где рисуем. символ - это цвет. + private char[][] matrix; + + public Canvas(int width, int height) { + this.width = width; + this.height = height; + this.matrix = new char[height + 2][width + 2]; + } + + /** + * Очищаем холст + */ + void clear() { + this.matrix = new char[height + 2][width + 2]; + } + + /** + * Печатаем переданную фигуру в указанных координатах цветом c. + * Если переданный массив содержит единицы, то на холсте им будут соответствовать символы - с. + */ + void drawMatrix(double x, double y, int[][] matrix, char c) { + int height = matrix.length; + int width = matrix[0].length; + + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + if (matrix[i][j] == 1) + setPoint(x + j, y + i, c); + } + } + } + + /** + * Ставим одну точку на холсте с координатами (x,y) и цветом - c. + */ + void setPoint(double x, double y, char c) { + int x0 = (int) Math.round(x); + int y0 = (int) Math.round(y); + if (y0 < 0 || y0 >= matrix.length) return; + if (x0 < 0 || x0 >= matrix[y0].length) return; + + matrix[y0][x0] = c; + } + + /** + * Печатаем содержимое холста на экран. + */ + void print() { + System.out.println(); + + for (int i = 0; i < height + 2; i++) { + for (int j = 0; j < width + 2; j++) { + System.out.print(" "); + System.out.print(matrix[i][j]); + System.out.print(" "); + } + + System.out.println(); + } + + System.out.println(); + System.out.println(); + System.out.println(); + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public char[][] getMatrix() { + return matrix; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2413/KeyboardObserver.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/KeyboardObserver.java new file mode 100644 index 0000000..32a0d01 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/KeyboardObserver.java @@ -0,0 +1,69 @@ +package com.javarush.task.task24.task2413; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.util.Queue; +import java.util.concurrent.ArrayBlockingQueue; + +public class KeyboardObserver extends Thread { + private Queue keyEvents = new ArrayBlockingQueue(100); + + private JFrame frame; + + @Override + public void run() { + frame = new JFrame("KeyPress Tester"); + frame.setTitle("Transparent JFrame Demo"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + frame.setUndecorated(true); + frame.setSize(400, 400); + frame.setExtendedState(JFrame.MAXIMIZED_BOTH); + frame.setLayout(new GridBagLayout()); + + frame.setOpacity(0.0f); + frame.setVisible(true); + + frame.addFocusListener(new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + //do nothing + } + + @Override + public void focusLost(FocusEvent e) { + System.exit(0); + } + }); + + + frame.addKeyListener(new KeyListener() { + + public void keyTyped(KeyEvent e) { + //do nothing + } + + public void keyReleased(KeyEvent e) { + //do nothing + } + + public void keyPressed(KeyEvent e) { + keyEvents.add(e); + } + }); + } + + + public boolean hasKeyEvents() { + return !keyEvents.isEmpty(); + } + + public KeyEvent getEventFromTop() { + return keyEvents.poll(); + } +} + diff --git a/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Stand.java b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Stand.java new file mode 100644 index 0000000..21a6beb --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/Stand.java @@ -0,0 +1,64 @@ +package com.javarush.task.task24.task2413; + +/** + * Подставка, с помощью которой отражаем мячик. + */ +public class Stand extends BaseObject { + //картинка для отрисовки + private static int[][] matrix = { + {1, 1, 1, 1, 1}, + {1, 0, 0, 0, 1}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, + }; + + //скорость + private double speed = 1; + //направление (-1 влево, +1 вправо) + private double direction = 0; + + public Stand(double x, double y) { + super(x, y, 3); + } + + /** + * Метод передвигает подставку в соответствии с текущим значением direction. + */ + void move() { + double dx = speed * direction; + x = x + dx; + + checkBorders(radius, Arkanoid.game.getWidth() - radius + 1, 1, Arkanoid.game.getHeight() + 1); + } + + /** + * direction устанавливается равным -1 + */ + void moveLeft() { + direction = -1; + } + + /** + * direction устанавливается равным +1 + */ + void moveRight() { + direction = 1; + } + + public double getSpeed() { + return speed; + } + + public double getDirection() { + return direction; + } + + /** + * Отрисовываем себя на холсте + */ + @Override + void draw(Canvas canvas) { + canvas.drawMatrix(x - radius + 1, y, matrix, 'M'); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task24/task2413/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..8c010c5 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task24/task2413/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,107 @@ +taskKey="com.javarush.task.task24.task2413.big20" + +Арканоид(20) + +Отличная работа! Я добавил пару методов, а также класс KeyboardObserver. + +Немного отдохни перед новым уровнем и поиграй. + +P.S. Только не забудь отрегулировать высоту консоли. + + +Арканоид(19) + +Осталось совсем чуть-чуть. + +В классе Arkanoid создай поле приватное isGameOver типа boolean. + +Реализуй метод checkBricksBump. +В этом методе надо проверить - не столкнулся ли шарик с каким-нибудь из "кирпичей". +Для проверки столкновения используй метод isIntersec. +Если шарик все-таки попал в кирпич, то: +а) шарик отлетает в случайном направлении: +double angle = Math.random() * 360; +ball.setDirection(angle); +б) кирпич умирает - надо удалить его из списка всех кирпичей. + +Реализуй метод checkStandBump. +В этом методе надо проверить - не ударился ли шарик о подставку. +Для проверки столкновения используй метод isIntersec. +Если шарик все-таки ударился о подставку, то: +шарик отлетает в случайным направлении вверх: +double angle = 90 + 20 * (Math.random() - 0.5); +ball.setDirection(angel); + +Реализуй метод checkEndGame. +Если координата y шарика больше чем высота поля игры (height), значит шарик улетел вниз за границу экрана. +В этом случае надо переменную isGameOver установить в true. + + + +Арканоид(18) + +Теперь вернемся к классу Arkanoid. + +Реализуй методы: +а) move() +В этом методе нужно двигать все движимые объекты (stand, ball). +б) draw(Canvas canvas) +В этом методе надо вызвать метод draw всех существующих объектов, которые его имеют. + + + +Арканоид(17) + +Еще подставке нужны методы: +а) move - см. move в BaseObject +Движение доски осуществляется горизонтально, поэтому мы меняем только координату х. +Подумай, как координата х зависит от направления (direction) и скорости (speed). Реализуй зависимость. +б) draw - см. draw в BaseObject +Его кодом я займусь сам. +в) moveLeft() - задает постоянное движение "подставки" влево +Просто присвой правильное значение переменной direction. +г) moveRight() - задает постоянное движение "подставки" вправо +Просто присвой правильное значение переменной direction. + + + +Арканоид(16) + +И наконец "подставка"! +Ей понадобятся такие приватные поля: +а) speed (скорость шарика) типа double; +б) direction (направление движения по оси x: 1 - вправо, -1 - влево, 0 - начальное значение, стоим на месте) типа double. + +Также создай для них геттеры. + +А еще с тебя конструктор, примерно вот такой: +public Stand(double x, double y) { +super(x, y, 3); +speed = 1; +direction = 0; +} + + + +Арканоид(15) + +Не поверишь, но и это еще не все. + +Во-первых нужен метод setDirection, +который не только устанавливает значение переменной direction, +но и вычисляет новые значения переменных dx и dy. + +Код должен выглядеть примерно так: +this.direction = direction; +double angel = Math.toRadians(direction); +dx = Math.cos(angle) * speed; +dy = -Math.sin(angle) * speed. + +Во-вторых шарик может удариться о стенку. +При этом он должен от нее отскочить. +Для этого нам понадобится еще один метод: +void checkRebound(int minx, int maxx, int miny, int maxy) +Создай его, а кодом я займусь сам. + + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2501/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2501/Solution.java new file mode 100644 index 0000000..bc62663 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2501/Solution.java @@ -0,0 +1,22 @@ +package com.javarush.task.task25.task2501; + +/* +Новые возможности! +*/ +public class Solution { + public static void main(String[] args) { + System.out.println(Alphabet.G.getLetterPosition()); + } + + public enum Alphabet { + A, B, C, D, E, + F, G, H, I, J, + K, L, M, N, O, + P, Q, R, S, T, + U, V, W, X, Y, Z; + + int getLetterPosition() { + return this.ordinal() + 1; + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task25/task2501/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task25/task2501/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..a3266f5 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task25/task2501/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,7 @@ +taskKey="com.javarush.task.task25.task2501" + +Новые возможности! + +Используя возможности enum-а реализуй метод getLetterPosition, который должен возвращать позицию буквы. Позиция буквы A - 1. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2502/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2502/Solution.java new file mode 100644 index 0000000..6948745 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2502/Solution.java @@ -0,0 +1,41 @@ +package com.javarush.task.task25.task2502; + +import java.util.*; + +/* +Машину на СТО не повезем! +*/ +public class Solution { + public static enum Wheel { + FRONT_LEFT, + FRONT_RIGHT, + BACK_LEFT, + BACK_RIGHT + } + + public static class Car { + protected List wheels; + + public Car() throws Exception { + wheels = new ArrayList(); + Wheel wheelEntry = null; + String[] dbArray = loadWheelNamesFromDB(); + if (dbArray.length != 4) { throw new Exception(); }; + for (String entry: dbArray){ + if ( (wheelEntry = Wheel.valueOf(entry)) == null) { throw new Exception();} + else { + wheels.add(wheelEntry); + } + } + } + + protected String[] loadWheelNamesFromDB() { + //this method returns mock data + return new String[]{"FRONT_LEFT", "FRONT_RIGHT", "BACK_LEFT", "BACK_RIGHT"}; + } + } + + public static void main(String[] args) throws Exception { + Car car = new Car(); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task25/task2502/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task25/task2502/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..a8bffe8 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task25/task2502/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,10 @@ +taskKey="com.javarush.task.task25.task2502" + +Машину на СТО не повезем! + +Инициализируй поле wheels используя данные из loadWheelNamesFromDB. +Выкинь исключение в случае некорректных данных. +Подсказка: если что-то не то с колесами, то это не машина! +Сигнатуры не менять. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2503/Column.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2503/Column.java new file mode 100644 index 0000000..326ecb2 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2503/Column.java @@ -0,0 +1,89 @@ +package com.javarush.task.task25.task2503; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +public enum Column implements Columnable { + Customer("Customer"), + BankName("Bank Name"), + AccountNumber("Account Number"), + Amount("Available Amount"); + + private String columnName; + + @Override + public String getColumnName() { + return this.columnName; + } + @Override + public boolean isShown() { + if (realOrder[this.ordinal()] == -1 ) { + return false; + } else { return true; } + } + + @Override + public void hide() { + int startNumberToChange = realOrder[this.ordinal()]; + realOrder[this.ordinal()] = -1; + for (int i = 0; i < realOrder.length; i++) { + if ( realOrder[i] > startNumberToChange) { + realOrder[i]--; + } + } + } + + + private static int[] realOrder; + + private Column(String columnName) { + this.columnName = columnName; + } + + /** + * Задает новый порядок отображения колонок, который хранится в массиве realOrder. + * realOrder[индекс в энуме] = порядок отображения; -1, если колонка не отображается. + * + * @param newOrder новая последовательность колонок, в которой они будут отображаться в таблице + * @throws IllegalArgumentException при дубликате колонки + */ + public static void configureColumns(Column... newOrder) { + realOrder = new int[values().length]; + for (Column column : values()) { + realOrder[column.ordinal()] = -1; + boolean isFound = false; + + for (int i = 0; i < newOrder.length; i++) { + if (column == newOrder[i]) { + if (isFound) { + throw new IllegalArgumentException("Column '" + column.columnName + "' is already configured."); + } + realOrder[column.ordinal()] = i; + isFound = true; + } + } + } + } + + /** + * Вычисляет и возвращает список отображаемых колонок в сконфигурированом порядке (см. метод configureColumns) + * Используется поле realOrder. + * + * @return список колонок + */ + public static List getVisibleColumns() { + List result = new LinkedList<>(); + Column[] list = Column.values(); + for (int i = 0; i < list.length; i++) { + for (int j = 0; j < list.length; j++){ + if (realOrder[j] == i) { + result.add(list[j]); + break; + } + } + } + + return result; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2503/Columnable.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2503/Columnable.java new file mode 100644 index 0000000..f505209 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2503/Columnable.java @@ -0,0 +1,27 @@ +package com.javarush.task.task25.task2503; + +public interface Columnable { + + /** + * @return полное имя колонки + */ + String getColumnName(); + + /** + * Возвращает true, если колонка видимая, иначе false + */ + boolean isShown(); + + /** + * Скрывает колонку - маркирует колонку -1 в массиве realOrder. + * Сдвигает индексы отображаемых колонок, которые идут после скрытой + */ + void hide(); + + /** + * Возвращает порядок константы в энуме. + * + * @return порядок константы в энуме + */ + int ordinal(); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2503/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2503/Solution.java new file mode 100644 index 0000000..7944917 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2503/Solution.java @@ -0,0 +1,32 @@ +package com.javarush.task.task25.task2503; + +/* +Свой enum +*/ +public class Solution { + /** + * Output: + *

+ * Available Amount + * Account Number + * Bank Name + * -------------------- + * Available Amount + * Bank Name + */ + public static void main(String[] args) { + + Column.configureColumns(Column.Amount, Column.AccountNumber, Column.BankName); + + for (Columnable columnable : Column.getVisibleColumns()) { + System.out.println(columnable.getColumnName()); + } + + System.out.println("--------------------"); + Column.AccountNumber.hide(); + + for (Columnable columnable : Column.getVisibleColumns()) { + System.out.println(columnable.getColumnName()); + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task25/task2503/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task25/task2503/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..0c7e803 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task25/task2503/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,11 @@ +taskKey="com.javarush.task.task25.task2503" + +Свой enum + +Реализуй интерфейс Columnable у Column, описание методов смотрите в джавадоках. +Реализуй логику метода Column.getVisibleColumns. +Метод Column.configureColumns уже реализован, его не меняй. +Создавать дополнительные поля нельзя. +Метод main не участвует в тестировании. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2504/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2504/Solution.java new file mode 100644 index 0000000..90ec962 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2504/Solution.java @@ -0,0 +1,36 @@ +package com.javarush.task.task25.task2504; + +/* +Switch для нитей +*/ +public class Solution { + public static void processThreads(Thread... threads) { + //implement this method - реализуйте этот метод + for (Thread entry: threads){ + switch (entry.getState()){ + case NEW: + entry.start(); + break; + case WAITING: + entry.interrupt(); + break; + case BLOCKED: + entry.interrupt(); + break; + case TIMED_WAITING: + entry.interrupt(); + break; + case RUNNABLE: + entry.isInterrupted(); + break; + case TERMINATED: + System.out.println(entry.getPriority()); + break; + } + } + } + + public static void main(String[] args) { + + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task25/task2504/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task25/task2504/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..fa13d8d --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task25/task2504/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,12 @@ +taskKey="com.javarush.task.task25.task2504" + +Switch для нитей + +Обработай список нитей в зависимости от состояния: +1. Если нить еще не запущена, то запусти ее. +2. Если нить в ожидании, то прерви ее. +3. Если нить работает, то проверь маркер isInterrupted. +4. Если нить прекратила работу, то выведи в консоль ее приоритет. +Используй switch. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2505/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2505/Solution.java new file mode 100644 index 0000000..97a8382 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2505/Solution.java @@ -0,0 +1,45 @@ +package com.javarush.task.task25.task2505; + +/* +Без дураков +*/ +public class Solution { + + public static void main(String[] args) { + MyThread myThread = new Solution().new MyThread("super secret key"); + myThread.start(); + } + + public class MyThread extends Thread { + private String secretKey; + + public MyThread(String secretKey) { + this.secretKey = secretKey; + setUncaughtExceptionHandler(new MyUncaughtExceptionHandler()); + setDaemon(false); + } + + @Override + public void run() { + throw new NullPointerException("it's an example"); + } + + private class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler { + + @Override + public void uncaughtException(Thread t, Throwable e) { + try { + Thread.currentThread().sleep(500); + System.out.println(String.format("%s, %s, %s", secretKey, t.getName(), e.getMessage() )); + + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + } + } + } + + + +} + diff --git "a/3.JavaMultithreading/src/com/javarush/task/task25/task2505/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task25/task2505/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..f6a0b5f --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task25/task2505/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,12 @@ +taskKey="com.javarush.task.task25.task2505" + +Без дураков + +1. Создай private class MyUncaughtExceptionHandler, который на перехват исключения должен подождать половину секунды, +а затем вывести на экран secretKey, имя трэда и сообщение возникшего исключения. +Используй String.format(...). Пример: +super secret key, Thread-0, it's an example +2. Разберись в последовательности выполняемого кода и обеспечь логирование возникновения исключения в п.1. +3. Метод main в тестировании не участвует. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2506/LoggingStateThread.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2506/LoggingStateThread.java new file mode 100644 index 0000000..496331e --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2506/LoggingStateThread.java @@ -0,0 +1,29 @@ +package com.javarush.task.task25.task2506; + +/** + * Created by PAKOT on 14.03.2017. + */ +public class LoggingStateThread extends Thread { + private Thread target; + private State prevState = null; + public LoggingStateThread (Thread target){ + this.target = target; + this.setDaemon(true); + } + + public void run(){ + + while (true){ + State state = target.getState(); + if (prevState == null) { + prevState = state; + System.out.println(state.toString()); + } else if (!state.equals(prevState)) { + System.out.println(state.toString()); + prevState = state; + } + if (state.equals(State.TERMINATED)) { break; } + + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2506/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2506/Solution.java new file mode 100644 index 0000000..f54a777 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2506/Solution.java @@ -0,0 +1,20 @@ +package com.javarush.task.task25.task2506; + +/* +Мониторинг состояния нити +*/ +public class Solution { + public static void main(String[] args) throws InterruptedException { + Thread target = new Thread(); + LoggingStateThread loggingStateThread = new LoggingStateThread(target); + + loggingStateThread.start(); + target.start(); //NEW + Thread.sleep(100); //RUNNABLE + target.join(100); + Thread.sleep(400); + target.interrupt(); //TERMINATED + Thread.sleep(500); + } + +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task25/task2506/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task25/task2506/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..17aceec --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task25/task2506/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,10 @@ +taskKey="com.javarush.task.task25.task2506" + +Мониторинг состояния нити + +Cоздай класс нити LoggingStateThread, +которая будет выводить в консоль все состояния (State) переданной в конструктор нити. +Нить LoggingStateThread должна сама завершаться после остановки переданной в конструктор нити. +Метод main не участвует в тестировании. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2507/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2507/Solution.java new file mode 100644 index 0000000..c8736e5 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2507/Solution.java @@ -0,0 +1,48 @@ +package com.javarush.task.task25.task2507; + +import java.io.IOException; +import java.io.InputStream; +import java.net.Socket; + +/* +Работать в поте лица! +*/ +public class Solution extends Thread { + private static final int BUFFER_SIZE = 2000; //2000 bytes + private final Socket socket; + private final InputStream in; + + public Solution(Socket socket) throws IOException { + this.socket = socket; + this.in = socket.getInputStream(); + } + + public void interrupt() { + try { + socket.close(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + super.interrupt(); + } + } + + public void run() { + try { + byte[] buf = new byte[BUFFER_SIZE]; + while (true) { + int count = in.read(buf); + if (count < 0) { + break; + } else { + if (count > 0) { + //process buffer here + } + } + } + } catch (IOException ignored) {} + } + + public static void main(String[] args) { + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task25/task2507/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task25/task2507/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..863d3ad --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task25/task2507/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,8 @@ +taskKey="com.javarush.task.task25.task2507" + +Работать в поте лица! + +Реализуй логику метода interrupt, который должен прерывать трэд предварительно закрыв используемые ресурсы. +Используй метод super-класса в блоке finally. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2508/CustomThreadManipulator.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2508/CustomThreadManipulator.java new file mode 100644 index 0000000..f4f6d2c --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2508/CustomThreadManipulator.java @@ -0,0 +1,6 @@ +package com.javarush.task.task25.task2508; + +public interface CustomThreadManipulator { + public void start(String threadName); + public void stop(); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2508/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2508/Solution.java new file mode 100644 index 0000000..0442fe3 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2508/Solution.java @@ -0,0 +1,40 @@ +package com.javarush.task.task25.task2508; + +/* +Не валять дурака +*/ +public class Solution +{ + /* + Output: + first + first + second + second + second + third + fifth + */ + public static void main(String[] args) throws InterruptedException { + CustomThreadManipulator manipulator = new TaskManipulator(); + + manipulator.start("first"); + Thread.sleep(150); + manipulator.stop(); + + manipulator.start("second"); + Thread.sleep(250); + manipulator.stop(); + + manipulator.start("third"); + Thread.sleep(50); + manipulator.stop(); + + manipulator.start("forth"); + manipulator.stop(); + + manipulator.start("fifth"); + Thread.sleep(1); + manipulator.stop(); + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2508/TaskManipulator.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2508/TaskManipulator.java new file mode 100644 index 0000000..179166b --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2508/TaskManipulator.java @@ -0,0 +1,31 @@ +package com.javarush.task.task25.task2508; + +public class TaskManipulator implements Runnable, CustomThreadManipulator { + private Thread thread; + + @Override + public void run() { + + while (!Thread.currentThread().isInterrupted()){ + try { + System.out.println(Thread.currentThread().getName()); + Thread.currentThread().sleep(75); + } catch (InterruptedException e) { + break; + } + } + } + + @Override + public void start(String threadName) { + TaskManipulator manipulator = new TaskManipulator(); + thread = new Thread(manipulator); + thread.setName(threadName); + thread.start(); + } + + @Override + public void stop() { + thread.interrupt(); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task25/task2508/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task25/task2508/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..d1a7675 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task25/task2508/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,7 @@ +taskKey="com.javarush.task.task25.task2508" + +Не валять дурака + +Восстанови логику класса TaskManipulator. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2509/CancellableTask.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2509/CancellableTask.java new file mode 100644 index 0000000..c7a3921 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2509/CancellableTask.java @@ -0,0 +1,10 @@ +package com.javarush.task.task25.task2509; + +import java.util.concurrent.Callable; +import java.util.concurrent.RunnableFuture; + +public interface CancellableTask extends Callable { + void cancel(); + + RunnableFuture newTask(); +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2509/SocketTask.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2509/SocketTask.java new file mode 100644 index 0000000..7d01940 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2509/SocketTask.java @@ -0,0 +1,38 @@ +package com.javarush.task.task25.task2509; + +import java.io.IOException; +import java.net.Socket; +import java.util.concurrent.FutureTask; +import java.util.concurrent.RunnableFuture; + +public abstract class SocketTask implements CancellableTask { + private Socket socket; + + protected synchronized void setSocket(Socket socket) { + this.socket = socket; + } + + public synchronized void cancel() { + try { + if (socket != null ) { + socket.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + public RunnableFuture newTask() { + return new FutureTask(this) { + public boolean cancel(boolean mayInterruptIfRunning) { + //close all resources here by using proper SocketTask method + //call super-class method in finally block + try { + SocketTask.this.cancel(); + } finally { + return super.cancel(mayInterruptIfRunning); + } + } + }; + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2509/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2509/Solution.java new file mode 100644 index 0000000..ef7f2f0 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2509/Solution.java @@ -0,0 +1,23 @@ +package com.javarush.task.task25.task2509; + +import java.util.concurrent.*; + +/* +Все не так легко, как кажется +*/ +public class Solution extends ThreadPoolExecutor { + public Solution(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue) { + super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); + } + + protected RunnableFuture newTaskFor(Callable callable) { + if (callable instanceof CancellableTask) { + return ((CancellableTask) callable).newTask(); + } else { + return super.newTaskFor(callable); + } + } + + public static void main(String[] args) { + } +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task25/task2509/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task25/task2509/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..2008a44 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task25/task2509/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,9 @@ +taskKey="com.javarush.task.task25.task2509" + +Все не так легко, как кажется + +1. Почитать в инете про Socket, ThreadPoolExecutor, RunnableFuture, Callable. +2. Реализуй логику метода cancel в классе SocketTask. +3. Реализуй логику метода cancel для локального класса внутри метода newTask в классе SocketTask. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2510/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2510/Solution.java new file mode 100644 index 0000000..a935a72 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2510/Solution.java @@ -0,0 +1,28 @@ +package com.javarush.task.task25.task2510; + +/* +Поживем - увидим +*/ +public class Solution extends Thread { + + public Solution() { + this.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler()); + } + + public class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler { + + @Override + public void uncaughtException(Thread t, Throwable e) { + if (e instanceof Error) { + System.out.println("Нельзя дальше работать"); + } else if (e instanceof Exception){ + System.out.println("Надо обработать"); + } else if (e instanceof Throwable){ + System.out.println("ХЗ"); + } + } + } + + public static void main(String[] args) { + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task25/task2510/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task25/task2510/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..e8bc081 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task25/task2510/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,11 @@ +taskKey="com.javarush.task.task25.task2510" + +Поживем - увидим + +Все исключения, которые возникают в процессе работы нити Solution, должны быть обработаны одним из вариантов: +1. Если это Error, то вывести в консоль "Нельзя дальше работать". +2. Если это Exception, то вывести в консоль "Надо обработать". +3. Если это Throwable, то вывести в консоль "ХЗ". +Реализуй эту логику. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2511/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2511/Solution.java new file mode 100644 index 0000000..a34dd52 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2511/Solution.java @@ -0,0 +1,71 @@ +package com.javarush.task.task25.task2511; + +import java.util.TimerTask; +import java.util.concurrent.ThreadFactory; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/* +Вооружаемся до зубов! +*/ +public class Solution extends TimerTask { + protected TimerTask original; + protected final Thread.UncaughtExceptionHandler handler; + + public Solution(TimerTask original) { + if (original == null) { + throw new NullPointerException(); + } + this.original = original; + + class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler{ + + @Override + public void uncaughtException(Thread t, Throwable e) { + String message = e.getMessage(); + String name = Thread.currentThread().getName(); + StringBuilder str = new StringBuilder(); + for (int i = 0; i < name.length(); i++){ + str.append("*"); + } + message = message.replaceAll(name, str.toString()); + System.out.println(message); + } + } + + this.handler = new MyUncaughtExceptionHandler(); //init handler here + + + } + + public void run() { + try { + original.run(); + throw new Throwable(); + } catch (Throwable cause) { + Thread currentThread = Thread.currentThread(); + handler.uncaughtException(currentThread, new Exception("Blah " + currentThread.getName() + " blah-blah-blah", cause)); + } + } + + public long scheduledExecutionTime() { + return original.scheduledExecutionTime(); + } + + public boolean cancel() { + return original.cancel(); + } + + public static void main(String[] args) { + Solution sol = new Solution(new TimerTask() { + @Override + public void run() { + + } + }); + Thread thread = new Thread(sol); + thread.start(); + } + + +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task25/task2511/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task25/task2511/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..d70c35f --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task25/task2511/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,10 @@ +taskKey="com.javarush.task.task25.task2511" + +Вооружаемся до зубов! + +Создай свой UncaughtExceptionHandler в виде локального класса внутри конструктора. +UncaughtExceptionHandler должен маскировать звездочками имя трэда и выводить в консоль описание возникшей ошибки. +"Thread-0" должно быть заменено на "********". +"Thread-4321" должно быть заменено на "***********". + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2512/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2512/Solution.java new file mode 100644 index 0000000..9e52a97 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2512/Solution.java @@ -0,0 +1,33 @@ +package com.javarush.task.task25.task2512; + +import java.util.ArrayList; + +/* +Живем своим умом +*/ +public class Solution implements Thread.UncaughtExceptionHandler { + + @Override + public void uncaughtException(Thread t, Throwable e) { + t.interrupt(); + ArrayList trace = new ArrayList(); + //trace.add(e.toString()); + while (true){ + if ( e.getCause() == null ) { + trace.add(e.toString()); + break; + } + trace.add(e.toString()); + e = e.getCause(); + + } + for (int i = trace.size() - 1; i >= 0; i--) { + System.out.println(trace.get(i)); + } + } + + public static void main(String[] args) throws Exception { + Solution sol = new Solution(); + sol.uncaughtException(Thread.currentThread(), new Exception("ABC", new RuntimeException("DEF", new IllegalAccessException("GHI")))); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task25/task2512/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task25/task2512/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..63c036a --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task25/task2512/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,14 @@ +taskKey="com.javarush.task.task25.task2512" + +Живем своим умом + +В классе Solution реализуй интерфейс UncaughtExceptionHandler, который должен: +1. прервать нить, которая бросила исключение. +2. вывести в консоль стек исключений, начиная с самого вложенного. +Пример исключения: new Exception("ABC", new RuntimeException("DEF", new IllegalAccessException("GHI"))) +Пример вывода: +java.lang.IllegalAccessException: GHI +java.lang.RuntimeException: DEF +java.lang.Exception: ABC + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2513/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2513/Solution.java new file mode 100644 index 0000000..997fee2 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2513/Solution.java @@ -0,0 +1,34 @@ +package com.javarush.task.task25.task2513; + +import java.util.Random; + +/* +Обеспечение отсутствия прерывания важной операции +*/ +public class Solution { + private static final Integer THRESHOLD_VALUE = 500; + private static final Random RANDOM = new Random(); + + public synchronized void moveMoney(Account from, Account to, int amount) { + from.setBalance(from.getBalance() - amount); + if (RANDOM.nextInt(5000) > THRESHOLD_VALUE) { + Thread.yield(); + } + to.setBalance(to.getBalance() + amount); + } + + class Account { + private int balance; + + public int getBalance() { + return balance; + } + + public void setBalance(int balance) { + this.balance = balance; + } + } + + public static void main(String[] args) { + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task25/task2513/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task25/task2513/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..4ea5ae3 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task25/task2513/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,10 @@ +taskKey="com.javarush.task.task25.task2513" + +Обеспечение отсутствия прерывания важной операции + +Просмотри метод moveMoney. +Если RANDOM.nextInt(5000) больше порогового значения THRESHOLD_VALUE, +то обеспечь переуступку кванта времени (переход хода для текущей нити). +Добавь этот код в единственное допустимое место. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task25/task2514/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task25/task2514/Solution.java new file mode 100644 index 0000000..91ed364 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task25/task2514/Solution.java @@ -0,0 +1,26 @@ +package com.javarush.task.task25.task2514; + +/* +Первый закон Финэйгла: если эксперимент удался, что-то здесь не так... +*/ +public class Solution { + public static class YieldRunnable implements Runnable { + private int index; + + public YieldRunnable(int index) { + this.index = index; + } + + public void run() { + System.out.println("begin-" + index); + Thread.yield(); + System.out.println("end-" + index); + } + } + + public static void main(String[] args) { + for (int i = 0; i < 10; i++){ + new Thread(new YieldRunnable(i)).start(); + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task25/task2514/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task25/task2514/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..5536615 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task25/task2514/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,7 @@ +taskKey="com.javarush.task.task25.task2514" + +Первый закон Финэйгла: если эксперимент удался, что-то здесь не так... + +Обеспечь переуступку кванта времени (переход хода для текущей нити) для последовательных выводов текста в консоль. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2601/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2601/Solution.java new file mode 100644 index 0000000..a916353 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2601/Solution.java @@ -0,0 +1,46 @@ +package com.javarush.task.task26.task2601; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; + +/* +Почитать в инете про медиану выборки +*/ +public class Solution { + + public static void main(String[] args) { + /*Integer[] array = {13, 8, 15, 5, 17, 14}; + array = sort(array); + for (Integer entry: array){ + System.out.println(entry); + }*/ + } + + public static Integer[] sort(Integer[] array) { + // Находим медианное значение + Arrays.sort(array); + final double mediana; + if ((array.length) % 2 == 0) { + int index = ( array.length / 2 ) - 1; + mediana = (array[index] + array[index + 1]) / 2d; + } else { + mediana = array[(array.length - 1) / 2]; + } + + // Сортируем массив по удаленности от медианного значения + Arrays.sort(array, new Comparator(){ + + @Override + public int compare(Object o1, Object o2) { + if (o1.equals(o2)) return 0; + if ((Math.abs(Double.parseDouble(o1.toString()) - mediana) - Math.abs(Double.parseDouble(o2.toString()) - mediana)) > 0 ) { return 1; } + else if ((Math.abs(Double.parseDouble(o1.toString()) - mediana) - Math.abs(Double.parseDouble(o2.toString()) - mediana)) < 0 ) { return -1; } + else return 0; + } + }); + + return array; + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task26/task2601/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task26/task2601/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..979f12d --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task26/task2601/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,14 @@ +taskKey="com.javarush.task.task26.task2601" + +Почитать в инете про медиану выборки + +Реализуй логику метода sort, который должен сортировать данные в массиве по удаленности от его медианы. +Верни отсортированный массив от минимального расстояния до максимального. +Если удаленность одинаковая у нескольких чисел, то сортируй их в порядке возрастания. +Пример входящего массива: +13, 8, 15, 5, 17 +медиана - 13 +отсортированный масив: +13, 15, 17, 8, 5 + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2602/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2602/Solution.java new file mode 100644 index 0000000..fbcdcde --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2602/Solution.java @@ -0,0 +1,38 @@ +package com.javarush.task.task26.task2602; + +import java.util.Comparator; +import java.util.Set; +import java.util.TreeSet; + +/* +Был бы ум - будет и успех +*/ +public class Solution { + public static void main(String[] args) { + Set soldiers = new TreeSet<>(); + soldiers.add(new Soldier("Ivanov", 170)); + soldiers.add(new Soldier("Petrov", 180)); + soldiers.add(new Soldier("Sidorov", 175)); + soldiers.add(new Soldier("Test", 170)); + + for (Soldier soldier : soldiers) { + System.out.println(soldier.name); + } + } + + public static class Soldier implements Comparable { + private String name; + private int height; + + public Soldier(String name, int height) { + this.name = name; + this.height = height; + } + + + @Override + public int compareTo(Soldier o) { + return o.height - this.height; + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task26/task2602/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task26/task2602/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..3515493 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task26/task2602/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,8 @@ +taskKey="com.javarush.task.task26.task2602" + +Был бы ум - будет и успех + +Солдаты всегда строились, строятся и будут строиться по убыванию роста. +Отсортируй солдат, предварительно подумав, что лучше использовать при таких условиях - Comparable или Comparator. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2603/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2603/Solution.java new file mode 100644 index 0000000..76a38db --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2603/Solution.java @@ -0,0 +1,29 @@ +package com.javarush.task.task26.task2603; + +import java.util.Comparator; + +/* +Убежденному убеждать других не трудно +*/ +public class Solution { + + public static class CustomizedComparator implements Comparator{ + private Comparator[] comparators; + public CustomizedComparator(Comparator... vararg){ + this.comparators = vararg; + } + + @Override + public int compare(Object o1, Object o2) { + for (int i = 0; i < comparators.length; i++){ + int compareValue = comparators[i].compare((T) o1, (T) o2); + if (compareValue != 0 ) { return compareValue; } + } + return 0; + } + } + + public static void main(String[] args) { + + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task26/task2603/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task26/task2603/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..5450d42 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task26/task2603/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,13 @@ +taskKey="com.javarush.task.task26.task2603" + +Убежденному убеждать других не трудно + +В таблице есть колонки, по которым можно сортировать. +Пользователь имеет возможность настроить под себя список колонок, которые будут сортироваться. +Напиши public static компаратор CustomizedComparator, который будет: +1. в конструкторе принимать массив компараторов. +2. сортировать данные в порядке, соответствующем последовательности компараторов. +Все переданные компараторы сортируют дженерик тип Т. +В конструктор передается как минимум один компаратор. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2604/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2604/Solution.java new file mode 100644 index 0000000..81d1ce2 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2604/Solution.java @@ -0,0 +1,64 @@ +package com.javarush.task.task26.task2604; + +import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Level; +import java.util.logging.Logger; + +/* +Для того, чтобы усовершенствовать ум, надо больше размышлять, чем заучивать +*/ +public class Solution extends Thread { + public static final String DEFAULT_JAVARUSH_THREAD_NAME = "JavaRushThread"; + + private static final AtomicInteger createdThreadIndex = new AtomicInteger(); + private static final AtomicInteger aliveThreadIndex = new AtomicInteger(); + private static final Logger log = Logger.getAnonymousLogger(); + + private static volatile boolean debugLifecycle = false; + + public Solution(Runnable runnable) { + this(runnable, DEFAULT_JAVARUSH_THREAD_NAME); + } + + public Solution(Runnable runnable, String name) { + super(runnable, name + "-" + createdThreadIndex.incrementAndGet()); + + setUncaughtExceptionHandler(new UncaughtExceptionHandler() { + public void uncaughtException(Thread t, Throwable e) { + log.log(Level.SEVERE, "An error occurred in thread " + t.getName(), e); + } + }); + } + + public static void main(String[] args) { + new Solution(new Runnable() { + @Override + public void run() { + System.out.println("test JavaRush Runnable for Solution class"); + } + }).start(); + + + new Solution(new Runnable() { + @Override + public void run() { + throw new RuntimeException("Oops"); + } + }).start(); + } + + public void run() { + if (debugLifecycle) { + log.log(Level.FINE, "Created " + getName()); + } + try { + aliveThreadIndex.incrementAndGet(); + super.run(); + } finally { + aliveThreadIndex.decrementAndGet(); + if (debugLifecycle) { + log.log(Level.FINE, "Exiting " + getName()); + } + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task26/task2604/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task26/task2604/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..adac129 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task26/task2604/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,7 @@ +taskKey="com.javarush.task.task26.task2604" + +Для того, чтобы усовершенствовать ум, надо больше размышлять, чем заучивать + +Расставь volatile там, где необходимо. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2605/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2605/Solution.java new file mode 100644 index 0000000..45122ab --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2605/Solution.java @@ -0,0 +1,70 @@ +package com.javarush.task.task26.task2605; + +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +/* +Трудолюбие - душа всякого дела и залог благосостояния +*/ +public class Solution { + private static ScheduledExecutorService interruptScheduledExecutor; + private static Thread taskThread; + private static RethrowableTask task; + + public static void main(String[] args) throws Exception { + runTaskBySchedule(new Runnable() { + @Override + public void run() { + System.out.println("A"); + throw new RuntimeException("it's test"); + } + }, 1_000, TimeUnit.MILLISECONDS + ); + + interruptScheduledExecutor.shutdown(); + } + + public static void runTaskBySchedule(final Runnable runnable, long timeout, TimeUnit unit) throws Exception { + task = new RethrowableTask(runnable); + taskThread = new Thread(task); + taskThread.start(); + + interruptScheduledExecutor = Executors.newScheduledThreadPool(1); + interruptScheduledExecutor.schedule(new Runnable() { + public void run() { + taskThread.interrupt(); + } + }, timeout, unit); + Thread.sleep(unit.toMillis(timeout)); + try { + task.rethrow(); + } catch (Throwable throwable) { + System.out.println(throwable.getMessage()); + } + } + + public static class RethrowableTask implements Runnable { + private volatile Throwable throwable; + private Runnable runnable; + + public RethrowableTask(Runnable runnable) { + this.runnable = runnable; + } + + public void run() { + try { + runnable.run(); + } catch (Throwable throwable) { + this.throwable = throwable; + } + } + + public void rethrow() throws Exception { + if (throwable != null) { + System.out.println("B"); + throw new Exception(throwable); + } + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task26/task2605/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task26/task2605/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..bac6868 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task26/task2605/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,7 @@ +taskKey="com.javarush.task.task26.task2605" + +Трудолюбие - душа всякого дела и залог благосостояния + +Расставь volatile там, где необходимо. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2606/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2606/Solution.java new file mode 100644 index 0000000..ca2232e --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2606/Solution.java @@ -0,0 +1,112 @@ +package com.javarush.task.task26.task2606; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +/* +Тот, кто любит труд, не нуждается в развлечениях +*/ +public class Solution { + /*private final URL javarushUrl; + private final URL javarushUrl1Child; + private final URL javarushVkGroupUrl; + private final URL javarushVkGroupUrl1Child; + private final URL javarushVkGroupUrl2Child; + private final URL javarushVkGroupUrl3Child; + + private volatile ExecutorService executorService; + private final Set urlsForProcessing = Collections.synchronizedSet(new HashSet<>()); + + public static void main(String[] args) throws MalformedURLException, InterruptedException { + Solution solution = new Solution(); + solution.start(); + Thread.sleep(1000); + solution.stop(); + } + + public Solution() throws MalformedURLException { + javarushUrl = new URL("http://javarush.ru/"); + javarushVkGroupUrl = new URL("http://vk.com/javarush"); + javarushUrl1Child = new URL("http://info.javarush.ru/page/FAQ/"); + javarushVkGroupUrl1Child = new URL("https://plus.google.com/114772402300089087607/about"); + javarushVkGroupUrl2Child = new URL("https://www.facebook.com/pages/Javarush/524321077686033"); + javarushVkGroupUrl3Child = new URL("https://twitter.com/javarush_ru"); + + urlsForProcessing.add(javarushUrl); + urlsForProcessing.add(javarushVkGroupUrl); + } + + public synchronized void start() { + executorService = Executors.newCachedThreadPool(); + for (URL url : urlsForProcessing) { + submitUrlTask(url); + } + urlsForProcessing.clear(); + } + + public synchronized void stop() throws InterruptedException { + try { + saveUnprocessedUrls(executorService.shutdownNow()); + if (executorService.awaitTermination(1_000, TimeUnit.MILLISECONDS)) { + saveUnprocessedUrls(getCancelledTasksFromExecutor()); + } + } finally { + executorService = null; + } + } + + private List getCancelledTasksFromExecutor() { + return Collections.EMPTY_LIST; + } + + protected List processPage(URL url) { + System.out.println(url + " will be processed"); + return getChildUrlByParent(url); + } + + private List getChildUrlByParent(URL url) { + List result = new ArrayList<>(); + + if (javarushUrl.equals(url)) { + result.add(javarushUrl1Child); + } else if (javarushVkGroupUrl.equals(url)) { + result.add(javarushVkGroupUrl1Child); + result.add(javarushVkGroupUrl2Child); + result.add(javarushVkGroupUrl3Child); + } + return result; + } + + private void saveUnprocessedUrls(List unprocessed) { + for (Runnable task : unprocessed) { + urlsForProcessing.add(((UrlTask) task).getPage()); + } + } + + private void submitUrlTask(URL url) { + executorService.execute(new UrlTask(url)); + } + + public class UrlTask implements Runnable { + private final URL url; + + private UrlTask(URL url) { + this.url = url; + } + + public void run() { + for (URL link : processPage(url)) { + if (Thread.currentThread().isInterrupted()) return; + submitUrlTask(link); + } + } + + public URL getPage() { + return url; + } + }*/ +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task26/task2606/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task26/task2606/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..4bb5e58 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task26/task2606/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,7 @@ +taskKey="com.javarush.task.task26.task2606" + +Тот, кто любит труд, не нуждается в развлечениях + +Расставь volatile там, где необходимо. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2607/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2607/Solution.java new file mode 100644 index 0000000..2fab39f --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2607/Solution.java @@ -0,0 +1,21 @@ +package com.javarush.task.task26.task2607; + +/* +Вежливость - это искусственно созданное хорошее настроение +*/ +public class Solution { + public static void main(String[] args) { + } + + public static class IntegerHolder{ + private int value; + + public synchronized int get(){ + return value; + } + + public synchronized void set(int value){ + this.value = value; + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task26/task2607/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task26/task2607/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..8881c8b --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task26/task2607/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,9 @@ +taskKey="com.javarush.task.task26.task2607" + +Вежливость - это искусственно созданное хорошее настроение + +В классе Solution создай public static класс IntegerHolder. +IntegerHolder должен быть для типа int (имя переменной должно быть value), быть thread safe и изменяемым. +В этом классе должны быть два public метода get и set. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2608/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2608/Solution.java new file mode 100644 index 0000000..dd6b33d --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2608/Solution.java @@ -0,0 +1,39 @@ +package com.javarush.task.task26.task2608; + +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/* +Мудрый человек думает раз, прежде чем два раза сказать +*/ +public class Solution { + int var1; + int var2; + int var3; + int var4; + Object lock1 = new Object(); + Object lock2 = new Object(); + + public Solution(int var1, int var2, int var3, int var4) { + this.var1 = var1; + this.var2 = var2; + this.var3 = var3; + this.var4 = var4; + } + + public int getSumOfVar1AndVar2() { + synchronized (lock1) { + return var1 + var2; + } + } + + public int getSumOfVar3AndVar4() { + synchronized (lock2){ + return var3 + var4; + } + } + + public static void main(String[] args) { + + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task26/task2608/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task26/task2608/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..4b9e052 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task26/task2608/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,9 @@ +taskKey="com.javarush.task.task26.task2608" + +Мудрый человек думает раз, прежде чем два раза сказать + +Все методы, кроме метода main, класса Solution должны быть thread safe. +Сделайте так, чтобы оба метода могли выполняться одновременно двумя различными тредами. +synchronized(this) для этого не подходит, используй другой объект для лока. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2609/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2609/Solution.java new file mode 100644 index 0000000..9893445 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2609/Solution.java @@ -0,0 +1,62 @@ +package com.javarush.task.task26.task2609; + +/* +Распределение элементов по корзинам с собственным локом +*/ +public class Solution { + private static final int NUMBER_LOCKS = 12; + private final Node[] buckets; + private final Object[] locks; + + static class Node { + public Node next; + public Object key; + public Object value; + } + + public Solution(int numberBuckets) { + buckets = new Node[numberBuckets]; + locks = new Object[NUMBER_LOCKS]; + for (int i = 0; i < NUMBER_LOCKS; i++) { + locks[i] = new Object(); + } + } + + private final int hash(Object key) { + return Math.abs(key.hashCode() % buckets.length); + } + + public Object get(Object key) { + int hash = hash(key); + synchronized (locks[hash % NUMBER_LOCKS]) { + for (Node m = buckets[hash]; m != null; m = m.next) { + if (m.key.equals(key)) return m.value; + } + } + return null; + } + + public void clear() { + for (int i = 0; i < buckets.length; i++) { + synchronized (locks[i % NUMBER_LOCKS]) { + buckets[i] = null; + } + } + } + + public static void main(String[] args) { + Solution sol = new Solution(3); + Node node1 = new Node(); + node1.key = 1; + Node node2 = new Node(); + node1.key = 2; + Node node3 = new Node(); + node1.key = 3; + sol.buckets[0] = node1; + sol.buckets[1] = node2; + sol.buckets[2] = node3; + sol.get(1); + sol.clear(); + + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task26/task2609/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task26/task2609/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..c42bd8c --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task26/task2609/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,7 @@ +taskKey="com.javarush.task.task26.task2609" + +Распределение элементов по корзинам с собственным локом + +В синхронизированных блоках используй нужный лок. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2610/Consumer.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2610/Consumer.java new file mode 100644 index 0000000..f7ca641 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2610/Consumer.java @@ -0,0 +1,31 @@ +package com.javarush.task.task26.task2610; + +import java.util.concurrent.BlockingQueue; + +import static java.lang.Thread.sleep; + +/** + * Created by Archmage on 19.03.2017. + */ +public class Consumer implements Runnable { + private BlockingQueue queue; + + public Consumer(BlockingQueue queue) { + this.queue = queue; + } + + @Override + public void run() { + try{ + while (true){ + String input; + if ((input = (String) queue.take()) != null) { + System.out.println(input); + } + Thread.sleep(300); + } + } catch (InterruptedException e){ + System.out.println(String.format("[%s] thread was terminated", Thread.currentThread().getName())); + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2610/Producer.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2610/Producer.java new file mode 100644 index 0000000..8f52402 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2610/Producer.java @@ -0,0 +1,23 @@ +package com.javarush.task.task26.task2610; + +import java.util.concurrent.BlockingQueue; + +public class Producer implements Runnable { + private BlockingQueue queue; + + public Producer(BlockingQueue queue) { + this.queue = queue; + } + + public void run() { + try { + int i = 0; + while (true) { + queue.put(String.valueOf(i++)); + Thread.sleep(300); + } + } catch (InterruptedException e) { + System.out.println(String.format("[%s] thread was terminated", Thread.currentThread().getName())); + } + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2610/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2610/Solution.java new file mode 100644 index 0000000..88c1d54 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2610/Solution.java @@ -0,0 +1,29 @@ +package com.javarush.task.task26.task2610; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/* +Мир скучен для скучных людей +*/ +public class Solution { + + public static void main(String[] args) throws Exception { + + BlockingQueue queue = new ArrayBlockingQueue(32); + + Producer producer = new Producer(queue); + Consumer consumer = new Consumer(queue); + + ExecutorService executorService = Executors.newCachedThreadPool(); + executorService.submit(producer); + executorService.submit(consumer); + + Thread.sleep(2000); + + executorService.shutdownNow(); + + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task26/task2610/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task26/task2610/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..43db659 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task26/task2610/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,8 @@ +taskKey="com.javarush.task.task26.task2610" + +Мир скучен для скучных людей + +Разберись с BlockingQueue. +По образу и подобию класса Producer создай класс Consumer, который будет выводить данные из BlockingQueue в консоль. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2611/Consumer.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2611/Consumer.java new file mode 100644 index 0000000..b39bcc8 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2611/Consumer.java @@ -0,0 +1,22 @@ +package com.javarush.task.task26.task2611; + +import java.util.concurrent.ConcurrentHashMap; + +public class Consumer implements Runnable { + private ConcurrentHashMap map; + + public Consumer(ConcurrentHashMap map) { + this.map = map; + } + + public void run() { + Thread currentThread = Thread.currentThread(); + while (!currentThread.isInterrupted()) { + if (!map.isEmpty()) { + for (String key : map.keySet()) { + System.out.println(map.remove(key)); + } + } + } + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2611/Producer.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2611/Producer.java new file mode 100644 index 0000000..1886387 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2611/Producer.java @@ -0,0 +1,29 @@ +package com.javarush.task.task26.task2611; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedDeque; + +/** + * Created by Archmage on 19.03.2017. + */ +public class Producer implements Runnable { + private ConcurrentHashMap map; + + public Producer(ConcurrentHashMap map){ + this.map = map; + } + + @Override + public void run() { + int i = 0; + try{ + while(true) { + i++; + map.put(String.valueOf(i), String.format("Some text for %s", i)); + Thread.sleep(500); + } + }catch (InterruptedException e){ + System.out.println(String.format("%s thread was terminated", Thread.currentThread().getName())); + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2611/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2611/Solution.java new file mode 100644 index 0000000..d3ff7f9 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2611/Solution.java @@ -0,0 +1,26 @@ +package com.javarush.task.task26.task2611; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/* +Мир не меняется, меняемся мы +*/ +public class Solution { + public static void main(String[] args) throws Exception { + ConcurrentHashMap map = new ConcurrentHashMap<>(); + + Producer producer = new Producer(map); + Consumer consumer = new Consumer(map); + + ExecutorService executorService = Executors.newCachedThreadPool(); + executorService.submit(producer); + executorService.submit(consumer); + + Thread.sleep(2000); + + executorService.shutdownNow(); + //finally 5 lines have to be printed + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task26/task2611/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task26/task2611/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..6a05242 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task26/task2611/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,10 @@ +taskKey="com.javarush.task.task26.task2611" + +Мир не меняется, меняемся мы + +Разберись с ConcurrentHashMap. +В отдельном файле создайте класс Producer, который будет: +1. каждые полсекунды добавлять в ConcurrentHashMap ключ и значение, где ключ - счетчик начиная с 1, значение - фраза: "Some text for i" , пример "Some text for 1". +2. при возникновении исключения выводить в консоль: "[TREAD_NAME] thread was terminated", пример "[thread-1] thread was terminated". + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task26/task2612/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task26/task2612/Solution.java new file mode 100644 index 0000000..b4d8b61 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task26/task2612/Solution.java @@ -0,0 +1,30 @@ +package com.javarush.task.task26.task2612; + +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/* +Весь мир играет комедию +*/ +public class Solution { + private Lock lock = new ReentrantLock(); + + public void someMethod() { + + if (lock.tryLock()){ + try { + ifLockIsFree(); + } finally { + lock.unlock(); + } + } else { + ifLockIsBusy(); + } + } + + public void ifLockIsFree() { + } + + public void ifLockIsBusy() { + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task26/task2612/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task26/task2612/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..c80e675 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task26/task2612/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,13 @@ +taskKey="com.javarush.task.task26.task2612" + +Весь мир играет комедию + +Почитать про java.util.concurrent.locks.Lock на http://docs.oracle.com/ (там все есть в джавадоках!) +Написать реализацию метода someMethod: +1. попытаться захватить лок +1.1. если лок занят, то вызвать метод ifLockIsBusy +1.2. если лок свободен, то: +1.2.1 вызвать метод ifLockIsFree +1.2.2 отпустить лок при любых условиях, даже если ifLockIsFree будет кидать исключение + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2701/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2701/Solution.java new file mode 100644 index 0000000..22b2889 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2701/Solution.java @@ -0,0 +1,28 @@ +package com.javarush.task.task27.task2701; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +/* +Избавляемся от меток +*/ +public class Solution { + public static void main(String[] args) throws IOException { + BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + String string = reader.readLine(); + String substring = reader.readLine(); + + if (isSubstringPresent(substring, string)) { + System.out.println("String: \n" + substring + "\nis present in the string: \n" + string); + } else { + System.out.println("String: \n" + substring + "\nis not present in the string: \n" + string); + } + } + + static boolean isSubstringPresent(String substring, String string) { + if (string.contains(substring)) { return true; } + else { return false; } + } +} + diff --git "a/3.JavaMultithreading/src/com/javarush/task/task27/task2701/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task27/task2701/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..e708ac5 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task27/task2701/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,9 @@ +taskKey="com.javarush.task.task27.task2701" + +Избавляемся от меток + +Избавьтесь от меток в методе isSubstringPresent сохранив логику. +Метод возвращает true, в случае если строка substring является подстрокой строки string, иначе false. +В коде должны отсутствовать операторы break и continue. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2702/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2702/Solution.java new file mode 100644 index 0000000..6b05881 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2702/Solution.java @@ -0,0 +1,21 @@ +package com.javarush.task.task27.task2702; + +/* +Нужный оператор +*/ +public class Solution { + public static void main(String args[]) { + label: + for (int i = 0; i < 10; i++) { + for (int j = 0; j < 10; j++) { + if (j > i) { + + System.out.println(); + continue label; + } + System.out.print("S"); + + } + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task27/task2702/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task27/task2702/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..d072ea4 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task27/task2702/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,7 @@ +taskKey="com.javarush.task.task27.task2702" + +Нужный оператор + +Вставьте в код единственную строчку - оператор (не break), чтобы на экран выводился треугольник из букв S. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2703/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2703/Solution.java new file mode 100644 index 0000000..68414c0 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2703/Solution.java @@ -0,0 +1,48 @@ +package com.javarush.task.task27.task2703; + +/* +Создаем deadlock +*/ +public class Solution { + static class Friend { + private final String name; + + public Friend(String name) { + this.name = name; + } + + public String getName() { + return this.name; + } + + public synchronized void bow(Friend bower) { + System.out.format("%s: %s" + + " has bowed to me!%n", + this.name, bower.getName()); + bower.bowBack(this); + } + + public synchronized void bowBack(Friend bower) { + System.out.format("%s: %s" + + " has bowed back to me!%n", + this.name, bower.getName()); + } + } + + public static void main(String[] args) { + final Friend alphonse = + new Friend("Alphonse"); + final Friend gaston = + new Friend("Gaston"); + new Thread(new Runnable() { + public void run() { + alphonse.bow(gaston); + } + }).start(); + new Thread(new Runnable() { + public void run() { + gaston.bow(alphonse); + } + }).start(); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task27/task2703/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task27/task2703/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..8b16d7c --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task27/task2703/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,8 @@ +taskKey="com.javarush.task.task27.task2703" + +Создаем deadlock + +Расставь модификаторы так, чтобы при работе с этим кодом появился deadlock. +Метод main порождает deadlock, поэтому не участвует в тестировании. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2704/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2704/Solution.java new file mode 100644 index 0000000..be33d5c --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2704/Solution.java @@ -0,0 +1,43 @@ +package com.javarush.task.task27.task2704; + +/* +Модификаторы и deadlock +*/ +public class Solution { + private final String field; + + public Solution(String field) { + this.field = field; + } + + public String getField() { + return field; + } + + public synchronized void sout(Solution solution) { + System.out.format("111: %s: %s %n", this.field, solution.getField()); + solution.sout2(this); + } + + public synchronized void sout2(Solution solution) { + System.out.format("222: %s: %s %n", this.field, solution.getField()); + solution.sout(this); + } + + public static void main(String[] args) { + final Solution solution = new Solution("first"); + final Solution solution2 = new Solution("second"); + new Thread(new Runnable() { + public void run() { + solution.sout(solution2); + } + }).start(); + + new Thread(new Runnable() { + public void run() { + solution2.sout(solution); + } + }).start(); + + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task27/task2704/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task27/task2704/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..0a77bb9 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task27/task2704/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,8 @@ +taskKey="com.javarush.task.task27.task2704" + +Модификаторы и deadlock + +Расставь модификаторы так, чтобы при работе с этим кодом появился deadlock. +Метод main порождает deadlock, поэтому не участвует в тестировании. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2705/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2705/Solution.java new file mode 100644 index 0000000..69235b6 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2705/Solution.java @@ -0,0 +1,46 @@ +package com.javarush.task.task27.task2705; + +/* +Второй вариант deadlock +*/ +public class Solution { + private final Object lock = new Object(); + + public synchronized void firstMethod() { + synchronized (lock) { + doSomething(); + } + } + + public void secondMethod() { + synchronized (lock) { + synchronized (this) { + doSomething(); + } + } + } + + private void doSomething() { + } + + public static void main(String[] args) throws InterruptedException { + final Solution sol = new Solution(); + Thread thread = new Thread(new Runnable() { + @Override + public void run() { + sol.firstMethod(); + } + }); + thread.start(); + + new Thread(new Runnable() { + @Override + public void run() { + sol.secondMethod(); + } + }).start(); + + Thread.sleep(1000); + System.out.println(thread.getState()); + } +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task27/task2705/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task27/task2705/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..6683ee4 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task27/task2705/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,8 @@ +taskKey="com.javarush.task.task27.task2705" + +Второй вариант deadlock + +В методе secondMethod расставь synchronized блоки так, +чтобы при использовании класса Solution нитями образовывался deadlock. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2706/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2706/Solution.java new file mode 100644 index 0000000..15aa45b --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2706/Solution.java @@ -0,0 +1,48 @@ +package com.javarush.task.task27.task2706; + +/* +Убираем deadlock +*/ +public class Solution { + public void safeMethod(Object obj1, Object obj2) { + Object syncObjMax = obj1.hashCode() > obj2.hashCode() ? obj1 : obj2; + Object syncObjMin = obj1.hashCode() > obj2.hashCode() ? obj2 : obj1; + synchronized (syncObjMax) { + longTimeMethod(); + synchronized (syncObjMin) { + unsafeMethod(obj1, obj2); + } + } + } + + public void longTimeMethod() { + try { + Thread.sleep(100); + } catch (InterruptedException ignored) { + } + } + + protected void unsafeMethod(Object obj1, Object obj2) { + System.out.println(obj1 + " " + obj2); + } + + public static void main(String[] args) { + final Object o1 = new Object(); + final Object o2 = new Object(); + final Solution solution = new Solution(); + + new Thread() { + @Override + public void run() { + solution.safeMethod(o1, o2); + } + }.start(); + + new Thread() { + @Override + public void run() { + solution.safeMethod(o2, o1); + } + }.start(); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task27/task2706/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task27/task2706/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..78c26b0 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task27/task2706/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,10 @@ +taskKey="com.javarush.task.task27.task2706" + +Убираем deadlock + +Используя стратегию избегания deadlock-а сделай так, чтобы он не возник. +Метод main не участвует в тестировании. +Действуй аналогично примеру из лекций. +Изменения вноси только в safeMethod. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2707/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2707/Solution.java new file mode 100644 index 0000000..8fe8f0b --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2707/Solution.java @@ -0,0 +1,73 @@ +package com.javarush.task.task27.task2707; + +import java.util.Date; + +/* +Определяем порядок захвата монитора +*/ +public class Solution { + + public void someMethodWithSynchronizedBlocks(Object obj1, Object obj2){ + synchronized (obj1) { + synchronized (obj2) { + System.out.println(obj1 + " " + obj2); + } + } + } + + private void referenceSyncMethod1(Object obj1) { + synchronized (obj1) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + } + } + } + + private void referenceSyncMethod2(Object obj1) { + synchronized (obj1) { + try { + Thread.sleep(1); + } catch (InterruptedException e) { + } + } + } + + public static boolean isNormalLockOrder(final Solution solution, final Object o1, final Object o2) throws Exception { + Thread thread = new Thread(new Runnable() { + @Override + public void run() { + solution.someMethodWithSynchronizedBlocks(o1, o2); + } + }); + Thread thread2 = new Thread(new Runnable() { + @Override + public void run() { + solution.referenceSyncMethod1(o1); + } + }); + Thread thread3 = new Thread(new Runnable() { + @Override + public void run() { + solution.referenceSyncMethod2(o2); + } + }); + + thread2.start(); + Thread.sleep(100); + thread.start(); + thread3.start(); + Thread.sleep(100); + if (thread3.getState().equals(Thread.State.TERMINATED)) { return true;} + else { return false; } + + } + + public static void main(String[] args) throws Exception { + final Solution solution = new Solution(); + final Object o1 = new Object(); + final Object o2 = new Object(); + + System.out.println(isNormalLockOrder(solution, o1, o2)); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task27/task2707/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task27/task2707/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..2822a1e --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task27/task2707/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,11 @@ +taskKey="com.javarush.task.task27.task2707" + +Определяем порядок захвата монитора + +Реализуй логику метода isNormalLockOrder, который должен определять: +соответствует ли порядок synchronized блоков в методе someMethodWithSynchronizedBlocks - +порядку передаваемых в него аргументов. +В случае, если сначала происходит синхронизация по o1, а потом по o2, метод должен вернуть true. +Если наоборот - false. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2708/Apartment.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2708/Apartment.java new file mode 100644 index 0000000..39c790e --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2708/Apartment.java @@ -0,0 +1,24 @@ +package com.javarush.task.task27.task2708; + +public class Apartment { + private String location; + private final RealEstate realEstate; + + public Apartment(RealEstate realEstate) { + this.realEstate = realEstate; + setLocation(String.valueOf(Math.random() * 10)); + } + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } + + public void revalidate(boolean isEmpty) { + if (isEmpty) + realEstate.up(this); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2708/RealEstate.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2708/RealEstate.java new file mode 100644 index 0000000..57d2a0a --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2708/RealEstate.java @@ -0,0 +1,43 @@ +package com.javarush.task.task27.task2708; + +import java.util.HashSet; +import java.util.Set; + +public class RealEstate { + + private final Set allApartments; + private final Set activeApartments; + + public RealEstate() { + allApartments = new HashSet(); + activeApartments = new HashSet(); + + //add some data + allApartments.add(new Apartment(this)); + allApartments.add(new Apartment(this)); + allApartments.add(new Apartment(this)); + allApartments.add(new Apartment(this)); + allApartments.add(new Apartment(this)); + allApartments.add(new Apartment(this)); + } + + public Set getAllApartments() { + return allApartments; + } + + public void up(Apartment apartment) { + activeApartments.add(apartment); + } + + public void revalidate() { + + activeApartments.clear(); + for (Apartment apartment : allApartments) { + boolean randomValue = Math.random() * 2 % 2 == 0; + synchronized (this) { + apartment.revalidate(randomValue); + } + } + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2708/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2708/Solution.java new file mode 100644 index 0000000..803bd09 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2708/Solution.java @@ -0,0 +1,51 @@ +package com.javarush.task.task27.task2708; + +import java.util.Set; + +/* +Убираем deadLock используя открытые вызовы +*/ +public class Solution { + public static void main(String[] args) { + final long deadLineTime = System.currentTimeMillis() + 5000; //waiting for 5 sec + + final RealEstate realEstate = new RealEstate(); + Set allApartments = realEstate.getAllApartments(); + + final Apartment[] apartments = allApartments.toArray(new Apartment[allApartments.size()]); + + for (int i = 0; i < 20; i++) { + new Thread(new Runnable() { + @Override + public void run() { + for (int i = 0; i < 10; i++) { + realEstate.revalidate(); + } + } + }, "RealEstateThread" + i).start(); + + new Thread(new Runnable() { + @Override + public void run() { + for (int i = 0; i < apartments.length; i++) { + apartments[i].revalidate(true); + } + } + }, "ApartmentThread" + i).start(); + } + + Thread deamonThread = new Thread(new Runnable() { + @Override + public void run() { + while (System.currentTimeMillis() < deadLineTime) + try { + Thread.sleep(2); + } catch (InterruptedException ignored) { + } + System.out.println("The dead lock occurred"); + } + }); + deamonThread.setDaemon(true); + deamonThread.start(); + } +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task27/task2708/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task27/task2708/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..abecc86 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task27/task2708/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,14 @@ +taskKey="com.javarush.task.task27.task2708" + +Убираем deadLock используя открытые вызовы + +Синхронизированные методы, которые вызывают внутри себя синхронизированные методы других классов, приводят к dead-lock-у. +1. Перенесите синхронизацию с метода в синхронизированный блок, куда поместите лишь необходимые части кода. +2. Уберите избыточную синхронизацию методов. +3. В стеке вызова методов не должно быть перекрестной синхронизации, +т.е. такого synchronizedMethodAClass().synchronizedMethodBClass().synchronizedMethodAClass() + +Этот способ избавления от дэдлока называется "открытые вызовы", о нем читайте в дополнительном материале к лекции. +Метод main не участвует в тестировании. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2709/ConsumerTask.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2709/ConsumerTask.java new file mode 100644 index 0000000..ce0eaaa --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2709/ConsumerTask.java @@ -0,0 +1,23 @@ +package com.javarush.task.task27.task2709; + +public class ConsumerTask implements Runnable { + private TransferObject transferObject; + protected volatile boolean stopped; + + public ConsumerTask(TransferObject transferObject) { + this.transferObject = transferObject; + new Thread(this, "ConsumerTask").start(); + } + + public void run() { + while (!stopped) { + synchronized (transferObject) { + transferObject.get(); + } + } + } + + public void stop() { + stopped = true; + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2709/ProducerTask.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2709/ProducerTask.java new file mode 100644 index 0000000..1fae1d3 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2709/ProducerTask.java @@ -0,0 +1,26 @@ +package com.javarush.task.task27.task2709; + +import java.util.concurrent.atomic.AtomicInteger; + +public class ProducerTask implements Runnable { + private TransferObject transferObject; + protected volatile boolean stopped; + static volatile AtomicInteger i = new AtomicInteger(0); + + public ProducerTask(TransferObject transferObject) { + this.transferObject = transferObject; + new Thread(this, "ProducerTask").start(); + } + + public void run() { + while (!stopped) { + synchronized (transferObject) { + transferObject.put(i.incrementAndGet()); + } + } + } + + public void stop() { + stopped = true; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2709/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2709/Solution.java new file mode 100644 index 0000000..0097c0f --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2709/Solution.java @@ -0,0 +1,16 @@ +package com.javarush.task.task27.task2709; + +/* +Producer–consumer +*/ +public class Solution { + public static void main(String args[]) throws InterruptedException { + TransferObject transferObject = new TransferObject(); + ProducerTask producerTask = new ProducerTask(transferObject); + ConsumerTask consumerTask = new ConsumerTask(transferObject); + + Thread.sleep(50); + producerTask.stop(); + consumerTask.stop(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2709/TransferObject.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2709/TransferObject.java new file mode 100644 index 0000000..e3261ea --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2709/TransferObject.java @@ -0,0 +1,33 @@ +package com.javarush.task.task27.task2709; + +public class TransferObject { + private int value; + protected volatile boolean isValuePresent = false; //use this variable + + public synchronized int get() { + while (!isValuePresent) { + try { + wait(); + } catch (InterruptedException e) { + } + } + System.out.println("Got: " + value); + isValuePresent = false; + notify(); + return value; + } + + public synchronized void put(int value) { + while (isValuePresent) { + try { + wait(); + } catch (InterruptedException e) { + } + } + this.value = value; + System.out.println("Put: " + value); + isValuePresent = true; + notify(); + + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task27/task2709/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task27/task2709/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..38f51f7 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task27/task2709/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,23 @@ +taskKey="com.javarush.task.task27.task2709" + +Producer–consumer + +В классе TransferObject расставь вызовы методов wait/notify/notifyAll, +чтобы обеспечить последовательное создание и получение объекта. +В методах run классов ConsumerTask и ProducerTask создай необходимые synchronized блоки. +Ожидаемый вывод: +... +Put: M +Got: M +Put: N +Got: N +Put: K +Got: K +... +где M, N, K - числа +Метод main не участвует в тестировании + +P.S. Всегда старайся использовать concurrent коллекции вместо ручной реализации wait/notify/notifyAll. +Задачи подобные этой позволяют лучше понять основы работы многопоточных приложений. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2710/Mail.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2710/Mail.java new file mode 100644 index 0000000..b1ca3a0 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2710/Mail.java @@ -0,0 +1,13 @@ +package com.javarush.task.task27.task2710; + +public class Mail { + private volatile String text; + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2710/MailServer.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2710/MailServer.java new file mode 100644 index 0000000..0886292 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2710/MailServer.java @@ -0,0 +1,26 @@ +package com.javarush.task.task27.task2710; + +public class MailServer implements Runnable { + private Mail mail; + + public MailServer(Mail mail) { + this.mail = mail; + } + + @Override + public void run() { + long beforeTime = System.currentTimeMillis(); + synchronized (mail) + { + try { + mail.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + //сделайте что-то тут - do something here + String name = Thread.currentThread().getName(); + long afterTime = System.currentTimeMillis(); + System.out.format("%s MailServer has got: [%s] in %d ms after start", name, mail.getText(), (afterTime - beforeTime)); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2710/Person.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2710/Person.java new file mode 100644 index 0000000..c27c6d5 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2710/Person.java @@ -0,0 +1,26 @@ +package com.javarush.task.task27.task2710; + +public class Person implements Runnable { + private final Mail mail; + + public Person(Mail mail) { + this.mail = mail; + } + + @Override + public void run() { + String name = Thread.currentThread().getName(); + try { + Thread.sleep(1000); + + //сделайте что-то тут - do something here + mail.setText("Person [" + name + "] has written an email 'AAA'"); + synchronized (mail){ + mail.notifyAll(); + } + //сделайте что-то тут - do something here + } catch (InterruptedException e) { + e.printStackTrace(); + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2710/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2710/Solution.java new file mode 100644 index 0000000..919fe2e --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2710/Solution.java @@ -0,0 +1,15 @@ +package com.javarush.task.task27.task2710; + +/* +Расставьте wait-notify +*/ +public class Solution { + public static void main(String[] args) { + Mail mail = new Mail(); + Thread server = new Thread(new MailServer(mail)); + Thread amigo = new Thread(new Person(mail)); + + server.start(); + amigo.start(); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task27/task2710/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task27/task2710/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..9893566 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task27/task2710/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,9 @@ +taskKey="com.javarush.task.task27.task2710" + +Расставьте wait-notify + +Расставь wait-notify. +Пример вывода: +Thread-0 MailServer has got: [Person [Thread-1] has written an email 'AAA'] in 1001 ms after start + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2711/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2711/Solution.java new file mode 100644 index 0000000..20213e5 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2711/Solution.java @@ -0,0 +1,25 @@ +package com.javarush.task.task27.task2711; + +import java.util.concurrent.CountDownLatch; + +/* +CountDownLatch +*/ +public class Solution { + + CountDownLatch latch = new CountDownLatch(1); + + public void someMethod() throws InterruptedException { + retrieveValue(); + latch.await(); + } + + void retrieveValue() { + System.out.println("Value retrieved."); + latch.countDown(); + } + + public static void main(String[] args) { + + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task27/task2711/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task27/task2711/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..86b3222 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task27/task2711/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,9 @@ +taskKey="com.javarush.task.task27.task2711" + +CountDownLatch + +Дана стандартная реализация методологии wait-notify. +Почитай про CountDownLatch и перепиши тело метода someMethod используя поле latch. +Весь лишний код удали из класса. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712 Restaurant (29).rar b/3.JavaMultithreading/src/com/javarush/task/task27/task2712 Restaurant (29).rar new file mode 100644 index 0000000..5fffc0c Binary files /dev/null and b/3.JavaMultithreading/src/com/javarush/task/task27/task2712 Restaurant (29).rar differ diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ConsoleHelper.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ConsoleHelper.java new file mode 100644 index 0000000..74c435c --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ConsoleHelper.java @@ -0,0 +1,41 @@ +package com.javarush.task.task27.task2712; + +import com.javarush.task.task27.task2712.kitchen.Dish; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +/** + * Created by ArchMage on 14.04.17. + */ +public class ConsoleHelper { + private static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + + public static void writeMessage(String message){ + System.out.println(message); + } + public static String readString() throws IOException { + return reader.readLine(); + } + + public static List getAllDishesForOrder() throws IOException{ + writeMessage(Dish.allDishesToString()); + writeMessage("Выберите блюда"); + List list = new ArrayList<>(); + String input = null; + while (!"exit".equals(input = reader.readLine())) { + try{ + Dish inputDish = Dish.valueOf(input); + list.add(inputDish); + } catch (IllegalArgumentException e){ + writeMessage("Блюдо отсутствует в меню"); + } + + } + return list; + } + +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/DirectorTablet.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/DirectorTablet.java new file mode 100644 index 0000000..cc416fc --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/DirectorTablet.java @@ -0,0 +1,50 @@ +package com.javarush.task.task27.task2712; + +import com.javarush.task.task27.task2712.statistic.StatisticManager; + +import java.math.BigDecimal; +import java.text.SimpleDateFormat; +import java.util.*; + +/** + * Created by ArchMage on 25.04.17. + */ +public class DirectorTablet { + + public void printAdvertisementProfit(){ + Map amountPerDay = StatisticManager.getInstance().getAmountPerDay(); + Double totalValue = 0d; + SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-yyyy", Locale.ENGLISH); + + for (Map.Entry entry : amountPerDay.entrySet()){ + Double amount = ((double) entry.getValue()) / 100; + Double roundedAmount = new BigDecimal(amount).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); + ConsoleHelper.writeMessage(dateFormat.format(entry.getKey()) + " - " + String.format("%.2f", roundedAmount).replaceAll(",", ".")); + totalValue += roundedAmount; + } + ConsoleHelper.writeMessage("Total - " + String.format("%.2f", totalValue).replaceAll(",", ".")); + } + public void printCookWorkloading(){ + Map> cookStatistic = StatisticManager.getInstance().getCookStatistic(); + SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-yyyy", Locale.ENGLISH); + boolean isFirstDisplay = true; + for (Map.Entry> entry : cookStatistic.entrySet()){ + if (isFirstDisplay) { + ConsoleHelper.writeMessage(dateFormat.format(entry.getKey())); + isFirstDisplay = false; + } else { + ConsoleHelper.writeMessage(""); + ConsoleHelper.writeMessage(dateFormat.format(entry.getKey())); + } + for (Map.Entry entryInList : entry.getValue().entrySet()){ + ConsoleHelper.writeMessage(String.format("%s - %d min", entryInList.getKey(), (entryInList.getValue() / 60))); + } + } + } + public void printActiveVideoSet(){ + + } + public void printArchivedVideoSet(){ + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Restaurant.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Restaurant.java new file mode 100644 index 0000000..d894521 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Restaurant.java @@ -0,0 +1,28 @@ +package com.javarush.task.task27.task2712; + +import com.javarush.task.task27.task2712.kitchen.Cook; +import com.javarush.task.task27.task2712.kitchen.Order; +import com.javarush.task.task27.task2712.kitchen.Waiter; + + +/** + * Created by ArchMage on 14.04.17. + */ +public class Restaurant { + public static void main(String[] args){ + Tablet tablet = new Tablet(5); + Cook cook = new Cook("Amigo"); + tablet.addObserver(cook); + Waiter waiter = new Waiter(); + cook.addObserver(waiter); + Order order = tablet.createOrder(); + DirectorTablet directorTablet = new DirectorTablet(); + + + directorTablet.printAdvertisementProfit(); + directorTablet.printCookWorkloading(); + directorTablet.printArchivedVideoSet(); + directorTablet.printActiveVideoSet(); + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Tablet.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Tablet.java new file mode 100644 index 0000000..cf63083 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/Tablet.java @@ -0,0 +1,67 @@ +package com.javarush.task.task27.task2712; + +import com.javarush.task.task27.task2712.ad.AdvertisementManager; +import com.javarush.task.task27.task2712.ad.NoVideoAvailableException; +import com.javarush.task.task27.task2712.kitchen.Order; + + +import java.io.IOException; +import java.util.Observable; +import java.util.Observer; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Created by ArchMage on 14.04.17. + */ +public class Tablet extends Observable { + protected final int number; + private static Logger logger = Logger.getLogger(Tablet.class.getName()); + private Observer observer; + + public Tablet(int number) { + this.number = number; + } + + public Order createOrder(){ + + try { + Order order = new Order(this); + if (!order.isEmpty()) { + ConsoleHelper.writeMessage(order.toString()); + setChanged(); + notifyObservers(order); + + // Часть 8 + // 5. Чтобы тестировать данную функциональность, нужно добавить вызов processVideos метода у AdvertisementManager. + // Очевидно, что этот метод должен вызываться во время создания заказа, а точнее — в параллельном режиме. + // Заказ готовится в то время, как видео смотрится. + // Добавьте вызов метода processVideos() в нужное место. + + try { + new AdvertisementManager(order.getTotalCookingTime() * 60).processVideos(); + } + catch (NoVideoAvailableException e){ + logger.log(Level.INFO, "No video is available for the order " + order.toString()); + } + } + return order; + } + + catch (IOException e){ + logger.log(Level.SEVERE, "Console is unavailable."); + return null; + } + + + } + + @Override + public String toString() { + return "Tablet{" + + "number=" + number + + '}'; + } + + +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/Advertisement.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/Advertisement.java new file mode 100644 index 0000000..54c7e1f --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/Advertisement.java @@ -0,0 +1,52 @@ +package com.javarush.task.task27.task2712.ad; + +/** + * Created by ArchMage on 18.04.17. + */ +public class Advertisement { + public Object content; + public String name; + private long initialAmount; + private int hits; + public int duration; + + // Часть 8 + //1. В классе Advertisement создай поле long amountPerOneDisplaying. + private long amountPerOneDisplaying; + + public Advertisement(Object content, String name, long initialAmount, int hits, int duration) { + this.content = content; + this.name = name; + this.initialAmount = initialAmount; + this.hits = hits; + this.duration = duration; + this.amountPerOneDisplaying = initialAmount / hits; + } + + // 2. В классе Advertisement создай геттеры для полей name, duration и amountPerOneDisplaying. + + + public String getName() { + return name; + } + + public int getHits() { + return hits; + } + + public int getDuration() { + return duration; + } + + public long getAmountPerOneDisplaying() { + return amountPerOneDisplaying; + } + + public void revalidate(){ + if (hits <= 0) { throw new UnsupportedOperationException(); } + hits--; + initialAmount -= amountPerOneDisplaying; + if (hits == 1) amountPerOneDisplaying = initialAmount; + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementManager.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementManager.java new file mode 100644 index 0000000..e31539e --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementManager.java @@ -0,0 +1,127 @@ +package com.javarush.task.task27.task2712.ad; + +import com.javarush.task.task27.task2712.ConsoleHelper; +import com.javarush.task.task27.task2712.statistic.StatisticManager; +import com.javarush.task.task27.task2712.statistic.event.VideoSelectedEventDataRow; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +/** + * Created by ArchMage on 18.04.17. + */ +public class AdvertisementManager { + // Часть 7 + // 4. В AdvertisementManager создадим final поле-ссылку на экземпляр AdvertisementStorage и назовем ее storage. + public final AdvertisementStorage storage = AdvertisementStorage.getInstance(); + + // В классе AdvertisementManager создай конструктор, который принимает один параметр — int timeSeconds. + // Создай соответствующее поле и сохраните это значение в него. + private int timeSeconds; + private List videosList; + + public AdvertisementManager(int timeSeconds) { + this.timeSeconds = timeSeconds; + } + + // 4. AdvertisementManager выполняет только одно единственное действие — обрабатывает рекламное видео. + // Поэтому создайте единственный публичный метод void processVideos(), его функционал опишем в следующем задании. + // А пока выведем в консоль «calling processVideos method» + + //Часть 9 + //2.2. Подобрать список видео из доступных, просмотр которых обеспечивает максимальную выгоду. + //2.4. Отобразить все рекламные ролики, отобранные для показа, в порядке уменьшения стоимости показа + // одного рекламного ролика в копейках. Вторичная сортировка — по увеличению стоимости показа одной секунды + // рекламного ролика в тысячных частях копейки. + + public void processVideos() throws NoVideoAvailableException{ + List availableVideos = new ArrayList(); + for (Advertisement entry: storage.list()){ + if (entry.getHits() > 0) { availableVideos.add(entry); } + } + //Collections.copy(storage.list(), availableVideos); + if (availableVideos == null || availableVideos.size() == 0) { + throw new NoVideoAvailableException(); + } else videoFitting(availableVideos, new ArrayList()); + + if (videosList == null || videosList.size() == 0) { + throw new NoVideoAvailableException(); + } + + Collections.sort(videosList, new Comparator() { + @Override + public int compare(Advertisement o1, Advertisement o2) { + if (Long.compare(o1.getAmountPerOneDisplaying(), o2.getAmountPerOneDisplaying()) == 0){ + return Long.compare(o1.getAmountPerOneDisplaying() * 1000 / o1.duration, o2.getAmountPerOneDisplaying() * 1000 / o2.duration); + }else return Long.compare(o2.getAmountPerOneDisplaying(), o1.getAmountPerOneDisplaying()); + } + }); + + StatisticManager.getInstance().register( + new VideoSelectedEventDataRow( + videosList, + totalAmount(videosList), + totalDuration(videosList))); + + for (Advertisement entry: videosList) { + ConsoleHelper.writeMessage(String.format("%s is displaying... %d, %d", + entry.getName(), + entry.getAmountPerOneDisplaying(), + entry.getAmountPerOneDisplaying() * 1000 / entry.getDuration())); + entry.revalidate(); + } + } + + private void videoFitting(List availableVideos, List fittingList){ + //List newAvailableList = new ArrayList(); + boolean isAlreadyMadeAdd = false; + for (int i = 0; i < availableVideos.size(); i++){ + if (isAlreadyMadeAdd) { + fittingList.remove(fittingList.size() - 1); + isAlreadyMadeAdd = false; + } + if (totalDuration(fittingList) + availableVideos.get(i).duration <= timeSeconds) { + fittingList.add(availableVideos.get(i)); + isAlreadyMadeAdd = true; + ArrayList newAvailableList = new ArrayList(availableVideos); + newAvailableList.remove(i); + videoFitting(newAvailableList, fittingList); + } + } + if (isAlreadyMadeAdd) { + fittingList.remove(fittingList.size() - 1); + isAlreadyMadeAdd = false; + } + if (totalAmount(videosList) < totalAmount(fittingList)) { + videosList = new ArrayList(fittingList); + } else if (totalAmount(videosList) == totalAmount(fittingList)) { + if (totalDuration(videosList) < totalDuration(fittingList)) { + videosList = new ArrayList(fittingList); + } else if (totalDuration(videosList) == totalDuration(fittingList)) { + if (videosList.size() > fittingList.size()) { + videosList = new ArrayList(fittingList); + } + } + } + } + + private static int totalDuration(List list){ + if (list == null || list.size() == 0) { return 0; } + int duration = 0; + for (Advertisement entry: list){ + duration += entry.duration; + } + return duration; + } + + private static long totalAmount(List list){ + if (list == null || list.size() == 0) { return 0; } + long amount = 0; + for (Advertisement entry: list){ + amount += entry.getAmountPerOneDisplaying(); + } + return amount; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementStorage.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementStorage.java new file mode 100644 index 0000000..d4db8d8 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/AdvertisementStorage.java @@ -0,0 +1,62 @@ +package com.javarush.task.task27.task2712.ad; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by ArchMage on 18.04.17. + */ +public class AdvertisementStorage { + private static AdvertisementStorage instance = new AdvertisementStorage(); + + // Часть 7 + // 1. Видео должно где-то храниться, пусть это будет список. + private final List videos = new ArrayList<>(); + + + // 3. В конструкторе класса добавим в список videos какие-то данные. + // ЕСЛИ НЕ ВЕРНУТЬ СПИСОК ВИДЕО В ИСХОДНОЕ СОСТОЯНИЕ, ТО 14 ПУНКТ ЗАДАЧИ НЕ ПРОХОДИТ!!! + // ОШИБКА: "Перед отображением видео должно быть зарегистрировано событие "видео выбрано". + + private AdvertisementStorage() { + Object someContent = new Object(); + videos.add(new Advertisement(someContent, "First Video", 5000, 100, 3 * 60)); // 3 min + videos.add(new Advertisement(someContent, "Second Video", 100, 10, 15 * 60)); //15 min + videos.add(new Advertisement(someContent, "Third Video", 400, 2, 10 * 60)); //10 min + /*videos.add(new Advertisement(someContent, "First Video", 100, 1, 100)); + videos.add(new Advertisement(someContent, "Second Video", 120, 1, 120)); + videos.add(new Advertisement(someContent, "Third Video", 400, 1, 400)); + videos.add(new Advertisement(someContent, "Fourth Video", 360, 1, 359)); + videos.add(new Advertisement(someContent, "FourthMoreMoney Video", 360, 1, 360)); + videos.add(new Advertisement(someContent, "Fifth Video", 30, 1, 30)); + videos.add(new Advertisement(someContent, "Sixth Video", 45, 1, 45));*//* + videos.add(new Advertisement(someContent, "First Video", 5000, 100, 15 * 60)); // 15 min + videos.add(new Advertisement(someContent, "Second Video", 100, 10, 3 * 60)); //3 min + videos.add(new Advertisement(someContent, "Third Video", 400, 2, 10 * 60)); //10 min + //videos.add(new Advertisement(someContent, "Forth Video", 12, 3, 1 * 60)); //1 min + //videos.add(new Advertisement(someContent, "Fifth Video", 8, 2, 1 * 60)); //1 min + //videos.add(new Advertisement(someContent, "Sixth Video", 16, 8, 1 * 60)); //1 min*/ + } + // 2. Чтобы как-то работать с видео, создай публичные методы: + // 2.1. list() — который вернет список всех существующих доступных видео. + public List list(){ + return videos; + } + // 2.2. add(Advertisement advertisement) — который добавит новое видео в список videos. + public void add(Advertisement advertisement){ + videos.add(advertisement); + } + + + + public static AdvertisementStorage getInstance(){ + return instance; + + // Ленивую инициализацию делать нельзя. Валидатор ругается. + /*if (instance == null) { + return new AdvertisementStorage(); + } else { + return instance; + }*/ + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/NoVideoAvailableException.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/NoVideoAvailableException.java new file mode 100644 index 0000000..5aced5d --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/ad/NoVideoAvailableException.java @@ -0,0 +1,11 @@ +package com.javarush.task.task27.task2712.ad; + +/** + * Created by ArchMage on 18.04.17. + */ + +// Часть 9 +// 1. Создадим unchecked исключение NoVideoAvailableException в пакете ad. + +public class NoVideoAvailableException extends RuntimeException { +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Cook.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Cook.java new file mode 100644 index 0000000..e21f5cd --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Cook.java @@ -0,0 +1,37 @@ +package com.javarush.task.task27.task2712.kitchen; + +import com.javarush.task.task27.task2712.ConsoleHelper; +import com.javarush.task.task27.task2712.Tablet; +import com.javarush.task.task27.task2712.statistic.StatisticManager; +import com.javarush.task.task27.task2712.statistic.event.CookedOrderEventDataRow; + +import java.util.Observable; +import java.util.Observer; + +/** + * Created by ArchMage on 17.04.17. + */ +public class Cook extends Observable implements Observer { + private String name; + + + public Cook(String name) { + this.name = name; + } + + @Override + public void update(Observable o, Object arg) { + ConsoleHelper.writeMessage("Start cooking - " + arg + ", cooking time " + ((Order) arg).getTotalCookingTime() + "min"); + StatisticManager statisticManager = StatisticManager.getInstance(); + Order order = (Order) arg; + Tablet tablet = (Tablet) o; + statisticManager.register(new CookedOrderEventDataRow(tablet.toString(), name, order.getTotalCookingTime() * 60, order.getDishes())); + setChanged(); + notifyObservers(arg); + } + + @Override + public String toString() { + return name; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Dish.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Dish.java new file mode 100644 index 0000000..85fc501 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Dish.java @@ -0,0 +1,42 @@ +package com.javarush.task.task27.task2712.kitchen; + +import java.util.Arrays; + +/** + * Created by ArchMage on 14.04.17. + */ +public enum Dish { + //Fish(11), + Fish(25), + Steak(30), + Soup(15), + Juice(5), + Water(3); + + private int duration; + + Dish(int i) { + duration = i; + } + + public int getDuration() { + return duration; + } + + public static String allDishesToString(){ + /*if (values().length == 0) { + return ""; + } + return Arrays.toString(values()).substring(1, Arrays.toString(values()).length() - 1);*/ + + StringBuilder strB = new StringBuilder(); + boolean isFirst = true; + for (Dish entry : Dish.values()){ + if (!isFirst) { + strB.append(", "); + } else { isFirst = false; } + strB.append(entry.toString()); + } + return strB.toString(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Order.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Order.java new file mode 100644 index 0000000..e49e40b --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Order.java @@ -0,0 +1,43 @@ +package com.javarush.task.task27.task2712.kitchen; + +import com.javarush.task.task27.task2712.ConsoleHelper; +import com.javarush.task.task27.task2712.Tablet; + +import java.io.IOException; +import java.util.List; + +/** + * Created by ArchMage on 14.04.17. + */ +public class Order { + protected List dishes; + private final Tablet tablet; + + public Order(Tablet tablet) throws IOException { + this.tablet = tablet; + dishes = ConsoleHelper.getAllDishesForOrder(); + } + + @Override + public String toString() { + if (dishes.isEmpty()) return ""; + else return "Your order: " + dishes + " of " + tablet; + } + + public int getTotalCookingTime(){ + int totalDureation = 0; + for (Dish entry : dishes){ + totalDureation += entry.getDuration(); + } + return totalDureation; + } + + public boolean isEmpty(){ + return (dishes == null || dishes.size() == 0); + } + + public List getDishes() { + return dishes; + } + +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Waiter.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Waiter.java new file mode 100644 index 0000000..ced8c9c --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/kitchen/Waiter.java @@ -0,0 +1,18 @@ +package com.javarush.task.task27.task2712.kitchen; + +import com.javarush.task.task27.task2712.ConsoleHelper; + +import java.util.Observable; +import java.util.Observer; + +/** + * Created by ArchMage on 18.04.17. + */ +public class Waiter implements Observer { + + @Override + public void update(Observable o, Object arg) { + ConsoleHelper.writeMessage(arg + " was cooked by " + o); + } + +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/StatisticManager.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/StatisticManager.java new file mode 100644 index 0000000..6cd1641 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/StatisticManager.java @@ -0,0 +1,156 @@ +package com.javarush.task.task27.task2712.statistic; + +import com.javarush.task.task27.task2712.ad.Advertisement; +import com.javarush.task.task27.task2712.kitchen.Cook; +import com.javarush.task.task27.task2712.statistic.event.CookedOrderEventDataRow; +import com.javarush.task.task27.task2712.statistic.event.EventDataRow; +import com.javarush.task.task27.task2712.statistic.event.EventType; +import com.javarush.task.task27.task2712.statistic.event.VideoSelectedEventDataRow; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; + +/** + * Created by ArchMage on 24.04.17. + */ +public class StatisticManager { + private static StatisticManager instance = new StatisticManager(); + private StatisticStorage statisticStorage = new StatisticStorage(); + private Set cooks = new HashSet(); + + private StatisticManager(){ + + } + + public static StatisticManager getInstance() { + return instance; + } + + public void register(EventDataRow data){ + statisticStorage.put(data); + } + + public void register(Cook cook){ + cooks.add(cook); + } + + public Map getAmountPerDay(){ + return statisticStorage.amountPerDay(); + } + + public Map> getCookStatistic() { return statisticStorage.cookStatistic(); } + + private class StatisticStorage{ + private Map> storage = new HashMap>();; + + public StatisticStorage(){ + + for (EventType entry: EventType.values()){ + storage.put(entry, new ArrayList()); + } + } + + private void put(EventDataRow data){ + EventType eventType = data.getType(); + List list = storage.get(eventType); + list.add(data); + } + + + + private Map amountPerDay(){ + //generateStatistic(); + + Map amountPerDay = new TreeMap(Collections.reverseOrder()); + List advertismentList = storage.get(EventType.SELECTED_VIDEOS); + for (EventDataRow entry: advertismentList){ + VideoSelectedEventDataRow row = (VideoSelectedEventDataRow) entry; + Date advDate = row.getDate(); + + Date referenceDate = null; + try { + referenceDate = new SimpleDateFormat( "dd.MM.yyyy" ).parse("" + advDate.getDate() + "." + + (advDate.getMonth() + 1) + "." + + (advDate.getYear() + 1900) ); + + } catch (ParseException e) { + } + + Long amountEntry = amountPerDay.get(referenceDate); + if (amountEntry == null) { + amountPerDay.put(referenceDate, row.getAmount()); + } else { + amountPerDay.put(referenceDate, row.getAmount() + amountEntry); + } + } + + return amountPerDay; + } + + private Map> cookStatistic(){ + Map> cookStatistic = new TreeMap>(Collections.reverseOrder()); + List cookStatisticsAll = storage.get(EventType.COOKED_ORDER); + for (EventDataRow entry: cookStatisticsAll){ + CookedOrderEventDataRow order = (CookedOrderEventDataRow) entry; + Date advDate = order.getDate(); + + Date referenceDate = null; + try { + referenceDate = new SimpleDateFormat( "dd.MM.yyyy" ).parse("" + advDate.getDate() + "." + + (advDate.getMonth() + 1) + "." + + (advDate.getYear() + 1900) ); + + } catch (ParseException e) { + } + Map currentCookStat = cookStatistic.get(referenceDate); + + if (currentCookStat == null) { + Map map = new TreeMap(); + map.put(order.getCookName(), Long.valueOf(order.getTime())); + cookStatistic.put(referenceDate, map); + } else { + Long cookerTime = currentCookStat.get(order.getCookName()); + if (cookerTime == null) { + currentCookStat.put(order.getCookName(), Long.valueOf(order.getTime())); + }else { + cookerTime += Long.valueOf(order.getTime()); + currentCookStat.put(order.getCookName(), cookerTime); + } + } + } + return cookStatistic; + } + + private void generateStatistic(){ + List dataList = storage.get(EventType.SELECTED_VIDEOS); + + VideoSelectedEventDataRow row = new VideoSelectedEventDataRow(new ArrayList(), 250, 50); + + Date date = null; + Date date2 = null; + Date date3 = null; + try { + date = new SimpleDateFormat( "dd.MM.yyyy" ).parse( "14.05.2013" ); + date2 = new SimpleDateFormat( "dd.MM.yyyy" ).parse( "13.05.2013" ); + date3 = new SimpleDateFormat( "dd.MM.yyyy" ).parse( "12.05.2013" ); + } catch (ParseException e) { + } + row.setCurrentDate(date); + dataList.add(row); + + row = new VideoSelectedEventDataRow(new ArrayList(), 102, 50); + row.setCurrentDate(date2); + dataList.add(row); + + row = new VideoSelectedEventDataRow(new ArrayList(), 250, 50); + row.setCurrentDate(date2); + dataList.add(row); + + row = new VideoSelectedEventDataRow(new ArrayList(), 54398, 50); + row.setCurrentDate(date3); + dataList.add(row); + } + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/CookedOrderEventDataRow.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/CookedOrderEventDataRow.java new file mode 100644 index 0000000..d88748c --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/CookedOrderEventDataRow.java @@ -0,0 +1,44 @@ +package com.javarush.task.task27.task2712.statistic.event; + +import com.javarush.task.task27.task2712.kitchen.Dish; + +import java.util.Date; +import java.util.List; + +/** + * Created by ArchMage on 25.04.17. + */ +public class CookedOrderEventDataRow implements EventDataRow { + private String tabletName; + private String cookName; + private int cookingTimeSeconds; + private List cookingDishs; + private Date currentDate; + + public CookedOrderEventDataRow(String tabletName, String cookName, int cookingTimeSeconds, List cookingDishs){ + this.tabletName = tabletName; + this.cookName = cookName; + this.cookingTimeSeconds = cookingTimeSeconds; + this.cookingDishs = cookingDishs; + currentDate = new Date(); + } + + @Override + public EventType getType() { + return EventType.COOKED_ORDER; + } + + @Override + public Date getDate() { + return currentDate; + } + + @Override + public int getTime() { + return cookingTimeSeconds; + } + + public String getCookName() { + return cookName; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/EventDataRow.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/EventDataRow.java new file mode 100644 index 0000000..4debd8c --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/EventDataRow.java @@ -0,0 +1,12 @@ +package com.javarush.task.task27.task2712.statistic.event; + +import java.util.Date; + +/** + * Created by ArchMage on 24.04.17. + */ +public interface EventDataRow { + EventType getType(); + Date getDate(); + int getTime(); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/EventType.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/EventType.java new file mode 100644 index 0000000..2b99a0e --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/EventType.java @@ -0,0 +1,10 @@ +package com.javarush.task.task27.task2712.statistic.event; + +/** + * Created by ArchMage on 25.04.17. + */ +public enum EventType { + COOKED_ORDER, + SELECTED_VIDEOS, + NO_AVAILABLE_VIDEO +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/NoAvailableVideoEventDataRow.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/NoAvailableVideoEventDataRow.java new file mode 100644 index 0000000..c52e200 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/NoAvailableVideoEventDataRow.java @@ -0,0 +1,31 @@ +package com.javarush.task.task27.task2712.statistic.event; + +import java.util.Date; + +/** + * Created by ArchMage on 25.04.17. + */ +public class NoAvailableVideoEventDataRow implements EventDataRow { + private int totalDuration; + private Date currentDate; + + public NoAvailableVideoEventDataRow(int totalDuration){ + this.totalDuration = totalDuration; + currentDate = new Date(); + } + + @Override + public EventType getType() { + return EventType.NO_AVAILABLE_VIDEO; + } + + @Override + public Date getDate() { + return currentDate; + } + + @Override + public int getTime() { + return totalDuration; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/VideoSelectedEventDataRow.java b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/VideoSelectedEventDataRow.java new file mode 100644 index 0000000..39a2720 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/statistic/event/VideoSelectedEventDataRow.java @@ -0,0 +1,49 @@ +package com.javarush.task.task27.task2712.statistic.event; + +import com.javarush.task.task27.task2712.ad.Advertisement; + +import java.util.Date; +import java.util.List; + +/** + * Created by ArchMage on 25.04.17. + */ +public class VideoSelectedEventDataRow implements EventDataRow { + private List optimalVideoSet; + private long amount; + private int totalDuration; + private Date currentDate; + + + public VideoSelectedEventDataRow(List optimalVideoSet, long amount, int totalDuration){ + this.optimalVideoSet = optimalVideoSet; + this.amount = amount; + this.totalDuration = totalDuration; + currentDate = new Date(); + + } + + @Override + public EventType getType() { + return EventType.SELECTED_VIDEOS; + } + + @Override + public Date getDate() { + return currentDate; + } + + // TODO: 25.04.17 Удалить после тестирования + public void setCurrentDate(Date currentDate) { + this.currentDate = currentDate; + } + + @Override + public int getTime() { + return totalDuration; + } + + public long getAmount() { + return amount; + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task27/task2712/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..486c72e --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task27/task2712/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,202 @@ +taskKey="com.javarush.task.task27.task2712.big16" + +Ресторан(16) + +Реализуем первый пункт статистики - какую сумму заработали на рекламе, сгруппировать по дням. + +1. В классе VideoSelectedEventDataRow создай геттер для поля amount. +В классе CookedOrderEventDataRow создай геттер для поля cookName. + +2. В StatisticManager создай метод (придумать самостоятельно), который из хранилища достанет все данные, +относящиеся к отображению рекламы, и посчитает общую прибыль за каждый день. +Дополнительно добавь вспомогательный метод get в класс хранилища, чтобы получить доступ к данным. + +3. Начнем с логики метода printAdvertisementProfit в классе DirectorTablet. +Используя метод из предыдущего пункта вывести в консоль в убывающем порядке даты и суммы. +Для каждой даты из хранилища событий, для которой есть показанная реклама, должна выводится сумма прибыли за показы рекламы для этой даты. +В конце вывести слово Total и общую сумму. +Пример: +14-May-2013 - 2.50 +13-May-2013 - 1.02 +12-May-2013 - 543.98 +Total - 547.50 + +4.Реализуем второй пункт статистики - загрузка (рабочее время) повара, сгруппировать по дням. + +В StatisticManager создай метод (придумать самостоятельно), который из хранилища достанет все данные, +относящиеся к работе повара, и посчитает общую продолжительность работы для каждого повара отдельно. + +5. Реализуем логику метода printCookWorkloading в классе DirectorTablet. +Используя метод из предыдущего пункта вывести в консоль в убывающем порядке даты, имена поваров и время работы в минутах (округлить в большую сторону). +Для каждой даты из хранилища событий, для которой есть запись о работе повара, должна выводится продолжительность работы в минутах для этой даты. +Если повар не работал в какой-то из дней, то с пустыми данными его НЕ выводить (см. 13-May-2013) +Поваров сортировать по имени +Пример: +14-May-2013 +Ivanov - 60 min +Petrov - 35 min + +13-May-2013 +Ivanov - 129 min + +12-May-2013 +Ivanov - 6 min +Petrov - 5 min + + +Требования: +1. В классе VideoSelectedEventDataRow должен быть создан геттер для поля amount. +2. В классе CookedOrderEventDataRow должен быть создан геттер для поля cookName. +3. Метод printAdvertisementProfit класса DirectorTablet должен быть реализован в соответствии с условием задачи. +4. Метод printCookWorkloading класса DirectorTablet должен быть реализован в соответствии с условием задачи. + + +Ресторан(15) + +Давай подумаем что нужно сделать, чтобы директор мог посмотреть: +1) какую сумму заработали на рекламе, сгруппировать по дням; +2) загрузка (рабочее время) повара, сгруппировать по дням; +3) список активных роликов и оставшееся количество показов по каждому; +4) список неактивных роликов (с оставшемся количеством показов равным нулю). + +Для каждого пункта добавим соответствующий метод в StatisticManager. +Директор будет вызывать метод, StatisticManager будет делать различные подсчеты. +Но директор должен из какого-то места вызвать эти методы. Дадим ему планшет, но с другим ПО. +Для этого создадим класс DirectorTablet, в котором будут дружелюбный интерфейс и возможность обращения к статистике. + +1. В корне задачи-проекта создай класс DirectorTablet. + +2. В классе DirectorTablet создай четыре void метода: +printAdvertisementProfit(), printCookWorkloading(), printActiveVideoSet(), printArchivedVideoSet() +Они соответствуют перечисленным четырем пунктам. + +3. Чтобы можно было проверить результат, добавим в метод main создание директорского планшета и вывод статистики +с помощью методов перечисленных выше. + +Нам понадобятся еще некоторые методы. +4. В EventDataRow создай методы: +Date getDate(), реализация которого вернет дату создания записи +int getTime(), реализация которого вернет время - продолжительность + +5. В StatisticManager void register(Cook cook), который зарегистрирует полученного повара. +Создай в классе StatisticManager множество (Set) поваров (cooks) и добавь в него повара. + +6. Реализуй необходимые геттеры у классов CookedOrderEventDataRow, NoAvailableVideoEventDataRow и VideoSelectedEventDataRow. + + + +Ресторан(14) + +1. Внутри StatisticStorage создай метод void put(EventDataRow data). + +2. Чтобы методом put(EventDataRow data) добавить объект data в данные карты, нужен тип события - EventType. +Будет правильно, если событие будет хранить в себе свой тип. Поэтому: +2.1. В интерфейс EventDataRow добавь метод EventType getType() +2.2. Реализуй этот метод в каждом классе-событии: CookedOrderEventDataRow, NoAvailableVideoEventDataRow, VideoSelectedEventDataRow + +3. Сделай так, чтобы к методу void put(EventDataRow data) нельзя было получить доступ за пределами класса StatisticManager. +Воспользуйся особенностями вложенных классов. + +Теперь остается расставить вызовы StatisticManager в те места, которые генерируют события. + +4. Зарегистрируй событие для повара во время приготовления еды. +Добавь геттер для поля dishes в класс Order, используйте его при создании события. + +5. Зарегистрируй событие "видео выбрано" перед отображением рекламы пользователю. + +6. Метод register с одним параметром типа EventDataRow должен регистрировать полученное событие в statisticStorage. + + + +Ресторан(13) + +Вернемся к методу register в классе StatisticManager. Он должен регистрировать события в хранилище. +Создадим хранилище : ) +Хранилище связано 1 к 1 с менеджером, т.е. один менеджер и одно хранилище на приложение. +К хранилищу может доступиться только StatisticManager. Поэтому... +Из вышеперечисленного следует, что хранилище должно быть приватным иннер классом. +Назовем его StatisticStorage. + +1. Внутри класса StatisticManager создать приватный иннер класс StatisticStorage. + +2. Чтобы менеджер мог получить доступ к хранилищу, нужно в классе StatisticManager создать поле statisticStorage типа StatisticStorage. +Инициализируй его экземпляром класса. + +3. StatisticStorage будет хранить данные внутри себя в виде мапы/словаря storage. +Связь StatisticStorage и Map должна быть has-a +Типы для мапы - > + +4. В конструкторе StatisticStorage инициализируй хранилище данными по-умолчанию: +например используя цикл, для каждого EventType добавь new ArrayList() + + + +Ресторан(12) + +У нас выделяются несколько событий: +*повар приготовил заказ +*выбрали набор видео-роликов для заказа +*нет ни одного видео-ролика, который можно показать во время приготовления заказа + +Это постоянные данные, поэтому для их хранения подходит энам. + +1. В пакете event создай enum EventType {COOKED_ORDER, SELECTED_VIDEOS, NO_AVAILABLE_VIDEO} + +2. В пакете event создай три класса, соответствующих значениям энама. Они будут(должны) представлять собой события. +Мы будем регистрировать их экземпляры в хранилище. +Имена классов с параметрами для конструкторов: +2.1. CookedOrderEventDataRow(String tabletName, String cookName, int cookingTimeSeconds, List cookingDishs) +где - tabletName - имя планшета +cookName - имя повара +cookingTimeSeconds - время приготовления заказа в секундах +cookingDishs - список блюд для приготовления +2.2. NoAvailableVideoEventDataRow(int totalDuration) +totalDuration - время приготовления заказа в секундах +2.3. VideoSelectedEventDataRow(List optimalVideoSet, long amount, int totalDuration) +optimalVideoSet - список видео-роликов, отобранных для показа +amount - сумма денег в копейках +totalDuration - общая продолжительность показа отобранных рекламных роликов +3. В классы, созданные в п.2., добавьте поле Date currentDate, которое проинициализируй в конструкторе текущей датой. + + + +Ресторан(11) + +Мы реализовали первые две фичи из трех. Напомню, первой была автоматизация приготовления заказа, +второй - подбор рекламных роликов, а третья - статистика для директора. Собственно, к ней мы и добрались. + +Нам нужно будет реализовать следующую функциональность: +1) подсчет статистики +2) отображение статистики директору + +Попробуем определиться с последовательностью действий. Чтобы отображать данные, сначала нужно их откуда-то получить. + +Есть два подхода: +ПЕРВЫЙ - применяется, когда сложно получить реальные данные, либо когда другой человек работает над получением данных: +1. захардкодить данные в приложении +2. отобразить хардкоженную статистику +3. сделать получение реальных данных - реальную статистику (интеграция с чужим кодом) + +ВТОРОЙ: +1. сделать получение реальных данных - реальную статистику +2. отобразить статистику + +Т.к. мы сами реализовываем данную функциональность, и статистика у нас не сложная, то выберем второй подход. +Начнем с получения реальных данных - реальной статистики. + +Идея такая: +Есть хранилище событий. +Когда у нас случается событие, то мы будем регистрировать это событие в хранилище. +На запрос директора мы будем фильтровать события из хранилища, вычислять необходимые данные и отображать их. + +Для начала нам нужно несколько классов. +1. Создадим пакет statistic, в котором создадим класс StatisticManager. С его помощью будем регистрировать события в хранилище. +2. У нас должно быть одно хранилище с одной точкой входа. Поэтому сделаем StatisticManager синглтоном. +3. Внутри пакета statistic создадим вложенный пакет event, в котором будут храниться классы, связанные с событиями. +4. Создадим в пакете event интерфейс EventDataRow. На данный момент он является интерфейсом-маркером, +т.к. не содержит методов, и по нему мы определяем, является ли переданный объект событием или нет. +5. В StatisticManager создадим публичный метод void register(EventDataRow data), который будет регистрировать событие в хранилище. +Мы вернемся к реализации позднее. + + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2801/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2801/Solution.java new file mode 100644 index 0000000..fabd6a6 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2801/Solution.java @@ -0,0 +1,37 @@ +package com.javarush.task.task28.task2801; + +/* +Осваиваем switch +*/ +public class Solution { + public static enum E1 {A, B, C, Y} + + public static enum E2 {D, E, F} + + public static enum E3 {D, E, F} + + public static void main(String[] args) { + Solution.switchTest(E1.C); + Solution.switchTest(E3.D); + Solution.switchTest(E2.D); + /* output + it's E1.C + undefined + it's E2.D + */ + } + + public static void switchTest(Enum obj) { + //add your code here + switch (obj.getClass().getSimpleName()){ + case "E1": + System.out.println(String.format("it's %s.%s", obj.getClass().getSimpleName(), obj.toString())); + break; + case "E2": + System.out.println(String.format("it's %s.%s", obj.getClass().getSimpleName(), obj.toString())); + break; + default: + System.out.println("undefined"); + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task28/task2801/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task28/task2801/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..df0b363 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task28/task2801/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,25 @@ +taskKey="com.javarush.task.task28.task2801" + +Осваиваем switch + +Реализуй логику метода switchTest: +1. Не используй условные операторы. +2. Используй 1 switch, у которого 2 case и 1 default. +3. Ожидаемый вывод: +Вывод для E1.A - "it's E1.A" +Вывод для E1.B - "it's E1.B" +Вывод для E1.C - "it's E1.C" +Вывод для E1.Y - "it's E1.Y" +Вывод для E2.D - "it's E2.D" +Вывод для E2.E - "it's E2.E" +Вывод для E2.F - "it's E2.F" +Вывод для всех других значений - "undefined". + + +Требования: +1. Класс Solution должен содержать метод switchTest и enums E1, E2, E3. +2. Реализуйте метод switchTest, используя 1 switch, у которого 2 case и 1 default. +3. Вывод в консоль должен соответствовать условию задачи. +4. Использовать условные операторы нельзя. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2802/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2802/Solution.java new file mode 100644 index 0000000..6dd70ba --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2802/Solution.java @@ -0,0 +1,63 @@ +package com.javarush.task.task28.task2802; + + +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicInteger; + +/* +Пишем свою ThreadFactory +*/ +public class Solution { + + public static void main(String[] args) { + class EmulateThreadFactoryTask implements Runnable { + @Override + public void run() { + emulateThreadFactory(); + } + } + + ThreadGroup group = new ThreadGroup("firstGroup"); + Thread thread = new Thread(group, new EmulateThreadFactoryTask()); + + ThreadGroup group2 = new ThreadGroup("secondGroup"); + Thread thread2 = new Thread(group2, new EmulateThreadFactoryTask()); + + thread.start(); + thread2.start(); + } + + public static class AmigoThreadFactory implements ThreadFactory{ + private static AtomicInteger fabricsCount = new AtomicInteger(0); + private AtomicInteger threadsCount = new AtomicInteger(0); + + public AmigoThreadFactory(){ + fabricsCount.set(fabricsCount.incrementAndGet()); + } + + @Override + public Thread newThread(Runnable r) { + String groupName = Thread.currentThread().getThreadGroup().getName(); + + threadsCount.set(threadsCount.incrementAndGet()); + Thread thread = new Thread(String.format("%s-pool-%d-thread-%d", groupName, fabricsCount.get(), threadsCount.get() )); + thread.setDaemon(false); + thread.setPriority(Thread.NORM_PRIORITY); + System.out.println(thread.getName()); + return thread; + } + } + + private static void emulateThreadFactory() { + AmigoThreadFactory factory = new AmigoThreadFactory(); + Runnable r = new Runnable() { + @Override + public void run() { + System.out.println(Thread.currentThread().getName()); + } + }; + factory.newThread(r).start(); + factory.newThread(r).start(); + factory.newThread(r).start(); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task28/task2802/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task28/task2802/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..e17be84 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task28/task2802/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,31 @@ +taskKey="com.javarush.task.task28.task2802" + +Пишем свою ThreadFactory + +В классе Solution создай публичный статический класс AmigoThreadFactory, реализующий интерфейс ThreadFactory. +1. Реализация интерфейсного метода - создайте и верните трэд, который должен: +1.1. не быть демоном, +1.2. иметь нормальный приоритет, +1.3. имя трэда должно иметь шаблон "GN-pool-A-thread-B", где +GN - это имя группы, +A - это номер фабрики инкрементируется в пределах класса начиная с 1, используйте AtomicInteger, +B - номер треда инкрементируется в пределах конкретной фабрики начиная с 1, используйте AtomicInteger. +2. Каждая фабрика должна иметь ту группу тредов (ThreadGroup), в которой она была создана. +3. Методы main и emulateThreadFactory не участвуют в тестировании. +Пример вывода: +secondGroup-pool-2-thread-1 +firstGroup-pool-1-thread-1 +firstGroup-pool-1-thread-3 +secondGroup-pool-2-thread-3 +firstGroup-pool-1-thread-2 +secondGroup-pool-2-thread-2 + + +Требования: +1. В классе Solution нужно создать класс public static AmigoThreadFactory, который реализует интерфейс ThreadFactory. +2. Фабрика AmigoThreadFactory должна создавать трэды, которые не являются демоном. +3. Фабрика AmigoThreadFactory должна создавать трэды, которые имеют нормальный приоритет. +4. Фабрика AmigoThreadFactory должна создавать имена для трэдов по шаблону "GN-pool-A-thread-B". +5. Каждая фабрика должна производить трэды с группой (ThreadGroup), в которой она была создана. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2803/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2803/Solution.java new file mode 100644 index 0000000..7c23455 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2803/Solution.java @@ -0,0 +1,24 @@ +package com.javarush.task.task28.task2803; + +import java.util.concurrent.ThreadLocalRandom; + +/* +ThreadLocalRandom +*/ +public class Solution { + + public static int getRandomIntegerBetweenNumbers(int from, int to) { + return ThreadLocalRandom.current().nextInt(from, to); + } + + public static double getRandomDouble() { + return ThreadLocalRandom.current().nextDouble(); + } + + public static long getRandomLongBetween0AndN(long n) { + return ThreadLocalRandom.current().nextLong(n); + } + + public static void main(String[] args) { + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task28/task2803/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task28/task2803/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..170ddc8 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task28/task2803/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,18 @@ +taskKey="com.javarush.task.task28.task2803" + +ThreadLocalRandom + +Класс Solution будет использоваться трэдами. +Реализуй логику всех методов, используйте класс ThreadLocalRandom. +getRandomIntegerBetweenNumbers должен возвращать случайный int между from и to. +getRandomDouble должен возвращать случайный double. +getRandomLongBetween0AndN должен возвращать случайный long между 0 и n. + + +Требования: +1. В классе Solution должны быть только статические методы. +2. Метод getRandomIntegerBetweenNumbers с помощью ThreadLocalRandom должен возвращать случайный int между from и to. +3. Метод getRandomDouble с помощью ThreadLocalRandom должен возвращать случайный double от 0 до 1. +4. Метод getRandomLongBetween0AndN с помощью ThreadLocalRandom должен возвращать случайный long между 0 и n. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2804/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2804/Solution.java new file mode 100644 index 0000000..3bc7424 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2804/Solution.java @@ -0,0 +1,81 @@ +package com.javarush.task.task28.task2804; + +import java.util.List; +import java.util.concurrent.ConcurrentSkipListSet; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.ThreadLocalRandom; + +/* +Magic class +*/ +public class Solution { + public static void main(String[] args) throws InterruptedException { + Solution solution = new Solution(); + //List list = null/* create object of this magic class here*/; + List list = new CopyOnWriteArrayList(); + solution.startUpdatingThread(list); + solution.copyOnWriteSolution(list); + solution.stopUpdatingThread(); + + /* The output example +size = 0 +Element :s781859336 +Element :s1453499757 +Element :s911312405 +Element :s-877520242 +Element :s-1636258097 +size = 5 + +Element2 :s781859336 +Element2 :s1453499757 +Element2 :s911312405 +Element2 :s-877520242 +Element2 :s-1636258097 +Element2 :s-1739827856 +Element2 :s-938954654 +Element2 :s925086217 +size = 8 + */ + } + + public void copyOnWriteSolution(List list) throws InterruptedException { + System.out.println("size = " + list.size()); + System.out.println(); + Thread.sleep(20); + for (String element : list) { //создает новую копию на момент создания итератора + System.out.println("Element :" + element); + } + System.out.println("size = " + list.size()); + System.out.println(); + Thread.sleep(20); + + for (String element : list) { //создает новую копию на момент создания итератора + System.out.println("Element2 :" + element); + } + System.out.println("size = " + list.size()); + stopUpdatingThread(); + } + + public void stopUpdatingThread() throws InterruptedException { + t.stop(); + t.join(); + } + + private Thread t; + + private void startUpdatingThread(final List list) { + t = new Thread(new Runnable() { + @Override + public void run() { + for (int i = 0; i < 20; i++) { + list.add("s" + ThreadLocalRandom.current().nextInt()); + try { + Thread.sleep(5); + } catch (InterruptedException e) { + } + } + } + }); + t.start(); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task28/task2804/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task28/task2804/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..4105258 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task28/task2804/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,19 @@ +taskKey="com.javarush.task.task28.task2804" + +Magic class + +В пакете java.util.concurrent найди такую реализацию List, у которой: +1. Итератор не содержит какие-либо данные, вставленные в список после создания итератора; +2. Внутри данные хранятся в виде массива; +3. Итератор гарантированно не бросает ConcurrentModificationException; +4. Допускаются все элементы включая null; +5. Исправь строку List list = null ... в методе main. + + +Требования: +1. Класс Solution изменять нельзя. +2. Реализацию методов startUpdatingThread и stopUpdatingThread менять нельзя. +3. Реализацию метода copyOnWriteSolution менять нельзя. +4. Добавь в main создание нужного экземпляра List согласно заданию. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2805/MyThread.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2805/MyThread.java new file mode 100644 index 0000000..77f182c --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2805/MyThread.java @@ -0,0 +1,64 @@ +package com.javarush.task.task28.task2805; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Created by ArchMage on 30.03.17. + */ +public class MyThread extends Thread{ + private static AtomicInteger count = new AtomicInteger(0); + + private int increment(){ + if (count.get() == Thread.MAX_PRIORITY) { + count.set(Thread.MIN_PRIORITY); + return 1; + } else { + count.set(count.incrementAndGet()); + int tempCount = count.get(); + if (tempCount > Thread.currentThread().getThreadGroup().getMaxPriority()) { + return Thread.currentThread().getPriority(); + } else { + return tempCount; + } + } + } + + public MyThread() { + this.setPriority(increment()); + } + + public MyThread(Runnable target) { + super(target); + this.setPriority(increment()); + } + + public MyThread(ThreadGroup group, Runnable target) { + super(group, target); + this.setPriority(increment()); + } + + public MyThread(String name) { + super(name); + this.setPriority(increment()); + } + + public MyThread(ThreadGroup group, String name) { + super(group, name); + this.setPriority(increment()); + } + + public MyThread(Runnable target, String name) { + super(target, name); + this.setPriority(increment()); + } + + public MyThread(ThreadGroup group, Runnable target, String name) { + super(group, target, name); + this.setPriority(increment()); + } + + public MyThread(ThreadGroup group, Runnable target, String name, long stackSize) { + super(group, target, name, stackSize); + this.setPriority(increment()); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2805/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2805/Solution.java new file mode 100644 index 0000000..bc23631 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2805/Solution.java @@ -0,0 +1,25 @@ +package com.javarush.task.task28.task2805; + +/* +Приоритеты в Threads +*/ +public class Solution { + + public static void main(String[] args) { + for (int i = 0; i < 12; i++) { + System.out.print(new MyThread().getPriority() + " "); + } + //output + //1 2 3 4 5 6 7 8 9 10 1 2 + + System.out.println(); + ThreadGroup group = new ThreadGroup("someName"); + group.setMaxPriority(7); + for (int i = 0; i < 12; i++) { + System.out.print(new MyThread(group, "name" + i).getPriority() + " "); + } + //output + //3 4 5 6 7 7 7 7 1 2 3 4 + } + +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task28/task2805/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task28/task2805/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..b546b57 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task28/task2805/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,17 @@ +taskKey="com.javarush.task.task28.task2805" + +Приоритеты в Threads + +В отдельном файле создай класс MyThread унаследовавшись от Thread. MyThread должен: +1. Иметь возможность быть созданным используя любой конструктор супер-класса (Alt+Insert). +2. Приоритет у трэдов должен проставляться циклично от минимального значения до максимального значения. +3. если у трэда установлена трэд-группа(ThreadGroup), то приоритет трэда не может быть больше максимального приоритета его трэд-группы. + + +Требования: +1. Создай класс MyThread в отдельном файле. Унаследуй его от Thread. +2. В классе MyThread должны присутствовать конструкторы, аналогичные конструкторам супер-класса. +3. Приоритет у объектов MyThread должен проставляться циклично, от MIN_PRIORITY до MAX_PRIORITY. +4. Если у объекта MyThread установлена ThreadGroup, приоритет MyThread не должен быть выше максимального приоритета ThreadGroup. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2806/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2806/Solution.java new file mode 100644 index 0000000..5e079bf --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2806/Solution.java @@ -0,0 +1,45 @@ +package com.javarush.task.task28.task2806; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/* +Знакомство с Executors +*/ +public class Solution { + public static void main(String[] args) throws InterruptedException { + //Add your code here + + ExecutorService executor = Executors.newFixedThreadPool(5); + for (int i = 1; i <= 10; i++){ + final int j = i; + executor.submit(new Runnable() { + @Override + public void run() { + doExpensiveOperation(j); + } + }); + } + executor.shutdown(); + executor.awaitTermination(5, TimeUnit.SECONDS); + + /* output example +pool-1-thread-2, localId=2 +pool-1-thread-1, localId=1 +pool-1-thread-3, localId=3 +pool-1-thread-1, localId=7 +pool-1-thread-1, localId=9 +pool-1-thread-4, localId=4 +pool-1-thread-5, localId=5 +pool-1-thread-2, localId=6 +pool-1-thread-1, localId=10 +pool-1-thread-3, localId=8 + */ + } + + private static void doExpensiveOperation(int localId) { + System.out.println(Thread.currentThread().getName() + ", localId="+localId); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task28/task2806/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task28/task2806/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..7d559ee --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task28/task2806/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,19 @@ +taskKey="com.javarush.task.task28.task2806" + +Знакомство с Executors + +1. В методе main создай фиксированный пул из 5 трэдов используя класс Executors. +2. В цикле отправь на исполнение в пул 10 задач Runnable. +3. У каждой задачи в методе run вызови метод doExpensiveOperation с порядковым номером задачи начиная с 1, см. пример вывода. +4. Запрети добавление новых задач на исполнение в пул (метод shutdown). +5. Дай пулу 5 секунд на завершение всех задач (метод awaitTermination и параметр TimeUnit.SECONDS). + + +Требования: +1. Используя класс Executors, создай в методе main фиксированный пул из 5 трэдов. +2. Пул должен принимать на исполнение 10 задач Runnable. +3. Каждая задача должна вызывать метод doExpensiveOperation с порядковым номером задачи, начиная с 1. +4. Запрети добавление новых задач на исполнение в пул. +5. На завершение всех задач в пуле нужно установить 5 секунд. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2807/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2807/Solution.java new file mode 100644 index 0000000..4cad783 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2807/Solution.java @@ -0,0 +1,45 @@ +package com.javarush.task.task28.task2807; + +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/* +Знакомство с ThreadPoolExecutor +*/ +public class Solution { + public static void main(String[] args) throws InterruptedException { + //Add your code here + LinkedBlockingQueue queue = new LinkedBlockingQueue<>(); + for (int i = 1; i <= 10; i++){ + final int j = i; + queue.add(new Runnable() { + + @Override + public void run() { + doExpensiveOperation(j); + } + }); + } + ThreadPoolExecutor poolExecuter = new ThreadPoolExecutor(3, 5, 1000, TimeUnit.MILLISECONDS, queue); + poolExecuter.prestartAllCoreThreads(); + poolExecuter.shutdown(); + poolExecuter.awaitTermination(5, TimeUnit.SECONDS); + /* output example +pool-1-thread-2, localId=2 +pool-1-thread-3, localId=3 +pool-1-thread-1, localId=1 +pool-1-thread-3, localId=5 +pool-1-thread-2, localId=4 +pool-1-thread-3, localId=7 +pool-1-thread-1, localId=6 +pool-1-thread-3, localId=9 +pool-1-thread-2, localId=8 +pool-1-thread-1, localId=10 + */ + } + + private static void doExpensiveOperation(int localId) { + System.out.println(Thread.currentThread().getName() + ", localId=" + localId); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task28/task2807/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task28/task2807/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..4aed6c5 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task28/task2807/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,28 @@ +taskKey="com.javarush.task.task28.task2807" + +Знакомство с ThreadPoolExecutor + +1. В методе main создай очередь LinkedBlockingQueue. +2. В цикле добавь в очередь 10 задач Runnable. +3. У каждой задачи в методе run вызови метод doExpensiveOperation с порядковым номером задачи начиная с 1, см. пример вывода. +4. Создай объект ThreadPoolExecutor со следующими параметрами: +- основное количество трэдов (ядро) = 3, +- максимальное количество трэдов = 5, +- время удержания трэда живым после завершения работы = 1000, +- тайм-юнит - миллисекунды, +- созданная в п.1. очередь с задачами. +5. Запусти все трэды, которые входят в основное кол-во трэдов - ядро, используй метод prestartAllCoreThreads. +6. Запрети добавление новых задач на исполнение в пул (метод shutdown). +7. Дай объекту ThreadPoolExecutor 5 секунд на завершение всех тасок (метод awaitTermination и параметр TimeUnit.SECONDS). + + +Требования: +1. В методе main нужно создать очередь LinkedBlockingQueue. +2. В цикле добавь в очередь 10 задач Runnable. +3. Нужно создать объект ThreadPoolExecutor с параметрами, указанными в задании. +4. С помощью метода prestartAllCoreThreads нужно запустить основные трэды. +5. Каждая задача должна вызывать метод doExpensiveOperation с порядковым номером задачи, начиная с 1. +6. Запрети добавление новых задач на исполнение в пул. +7. На завершение всех задач в пуле нужно установить 5 секунд. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2808/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2808/Solution.java new file mode 100644 index 0000000..9275efe --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2808/Solution.java @@ -0,0 +1,56 @@ +package com.javarush.task.task28.task2808; + + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.*; + +/* +Осваиваем Callable +*/ +public class Solution { + public static void main(String[] args) throws InterruptedException, ExecutionException { + List> futures = new ArrayList<>(); + ExecutorService executor = Executors.newFixedThreadPool(5); + for (int i = 1000; i <= 1010; i++) { + futures.add(executor.submit(getTask(i))); + } + + futures.add(executor.submit(getTask(10000000))); + + for(Future future : futures) { + System.out.println(future.get()); + } + + executor.shutdown(); + executor.awaitTermination(10, TimeUnit.SECONDS); + +/* output +500500 +501501 +502503 +503506 +504510 +505515 +506521 +507528 +508536 +509545 +510555 +50000005000000 +*/ + } + + public static Callable getTask(final int i) { + return new Callable() { + @Override + public String call() throws Exception { + long summ = 0; + for (int j = 1; j <= i; j++ ){ + summ +=j; + } + return String.valueOf(summ); + } + }; + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task28/task2808/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task28/task2808/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..036951e --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task28/task2808/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,16 @@ +taskKey="com.javarush.task.task28.task2808" + +Осваиваем Callable + +Реализуй логику метода getTask, который должен возвращать объект Callable. +Объект Callable должен вычислять сумму всех чисел от 1 до переданного числа i включая его, и возвращать его в виде строки. +Метод main не участвует в тестировании. + + +Требования: +1. Класс Solution должен содержать статический метод getTask(int). +2. Метод getTask должен возвращать объект Callable. +3. Объект Callable должен возвращать в виде строки сумму всех чисел от 1 до переданного числа i, включая его +4. Сумма должна правильно считаться для чисел произвольной длины. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2809/Character.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2809/Character.java new file mode 100644 index 0000000..e276185 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2809/Character.java @@ -0,0 +1,26 @@ +package com.javarush.task.task28.task2809; + +import java.util.concurrent.ThreadLocalRandom; + +public abstract class Character implements Runnable { + protected abstract int getId(); + + public void run() { + System.out.println(toString() + " вступил в игру"); + doSomething(); + System.out.println(toString() + " умер"); + } + + private void doSomething() { + try { + Thread.currentThread().sleep(ThreadLocalRandom.current().nextInt(10, 100)); + } catch (InterruptedException ignored) { + } + } + + @Override + public String toString() { + return getClass().getSimpleName() + " #" + getId(); + } + +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2809/Plant.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2809/Plant.java new file mode 100644 index 0000000..6ac7a67 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2809/Plant.java @@ -0,0 +1,12 @@ +package com.javarush.task.task28.task2809; + +import java.util.concurrent.atomic.AtomicInteger; + +public class Plant extends Character { + private final static AtomicInteger idSequence = new AtomicInteger(); + private final int id = idSequence.incrementAndGet(); + + protected int getId() { + return id; + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2809/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2809/Solution.java new file mode 100644 index 0000000..ddc65ac --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2809/Solution.java @@ -0,0 +1,45 @@ +package com.javarush.task.task28.task2809; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Phaser; + +/* +Plants vs Zombies +*/ +public class Solution { + public static void main(String[] args) throws InterruptedException { + List characters = new ArrayList<>(); + characters.add(new Plant()); + characters.add(new Plant()); + characters.add(new Zombie()); + characters.add(new Zombie()); + characters.add(new Zombie()); + start(characters); + } + + private static boolean isEveryoneReady = false; + + private static void start(List characters) throws InterruptedException { + final Phaser phaser = new Phaser(1 + characters.size()); + + for (final Character character : characters) { + final String member = character.toString(); + System.out.println(member + " присоединился к игре"); + new Thread() { + @Override + public void run() { + System.out.println(member + " готовится играть"); + + phaser.arriveAndAwaitAdvance(); + if (!isEveryoneReady) { + isEveryoneReady = true; + System.out.println("Игра началась!"); + } + character.run(); + } + }.start(); + } + phaser.arriveAndDeregister(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2809/Zombie.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2809/Zombie.java new file mode 100644 index 0000000..13f671b --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2809/Zombie.java @@ -0,0 +1,13 @@ +package com.javarush.task.task28.task2809; + +import java.util.concurrent.atomic.AtomicInteger; + +public class Zombie extends Character { + private final static AtomicInteger idSequence = new AtomicInteger(); + private final int id = idSequence.incrementAndGet(); + + protected int getId() { + return id; + } +} + diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2809/output.txt b/3.JavaMultithreading/src/com/javarush/task/task28/task2809/output.txt new file mode 100644 index 0000000..a708313 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2809/output.txt @@ -0,0 +1,21 @@ +Plant #1 присоединился к игре +Plant #2 присоединился к игре +Plant #1 готовится играть +Zombie #1 присоединился к игре +Zombie #2 присоединился к игре +Zombie #3 присоединился к игре +Plant #2 готовится играть +Zombie #2 готовится играть +Zombie #1 готовится играть +Zombie #3 готовится играть +Игра началась! +Zombie #1 вступил в игру +Zombie #3 вступил в игру +Plant #1 вступил в игру +Zombie #2 вступил в игру +Plant #2 вступил в игру +Zombie #2 умер +Plant #2 умер +Plant #1 умер +Zombie #3 умер +Zombie #1 умер \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task28/task2809/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task28/task2809/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..a55f173 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task28/task2809/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,23 @@ +taskKey="com.javarush.task.task28.task2809" + +Plants vs Zombies + +1. Почитай про java.util.concurrent.Phaser. +2. Расставь методы в нужных местах: +-arriveAndDeregister() - начинает запускать методы run у тасок, +-arriveAndAwaitAdvance() - ждет, когда все трэды будут созданы. + +Пример вывода см. в output.txt. +Логика: +Сначала все персонажи присоединяются к игре. +После того, как все персонажи присоединятся к игре и готовы играть, выводится фраза "Игра началась!". +После этого персонажи вступают в игру, после чего умирают. + + +Требования: +1. Класс Character менять не нужно. +2. Классы Plant и Zombie менять не нужно. +3. В классе Solution вызови метод phaser.arriveAndDeregister в правильном месте. +4. В классе Solution вызови метод phaser.arriveAndAwaitAdvance в правильном месте. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2811/ReadWriteMap.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2811/ReadWriteMap.java new file mode 100644 index 0000000..375c8c2 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2811/ReadWriteMap.java @@ -0,0 +1,35 @@ +package com.javarush.task.task28.task2811; + +import java.util.Map; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +public class ReadWriteMap { + private final Map map; + private final ReadWriteLock lock = new ReentrantReadWriteLock(); + private final Lock readLock = lock.readLock(); + private final Lock writeLock = lock.writeLock(); + + public ReadWriteMap(Map map) { + this.map = map; + } + + public V put(K key, V value) { + try { + writeLock.lock(); + return map.put(key, value); + } finally { + writeLock.unlock(); + } + } + + public V get(K key) { + try { + readLock.lock(); + return map.get(key); + } finally { + readLock.unlock(); + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2811/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2811/Solution.java new file mode 100644 index 0000000..fbb00a6 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2811/Solution.java @@ -0,0 +1,13 @@ +package com.javarush.task.task28.task2811; + +/* +ReentrantReadWriteLock +*/ + +import java.util.LinkedHashMap; + +public class Solution { + public static void main(String[] args) { + ReadWriteMap linkedSafeMap = new ReadWriteMap(new LinkedHashMap()); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task28/task2811/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task28/task2811/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..9678539 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task28/task2811/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,21 @@ +taskKey="com.javarush.task.task28.task2811" + +ReentrantReadWriteLock + +Класс ReadWriteMap должен предоставлять корректный доступ к объекту Map из многих потоков, но в его реализации +были допущены ошибки. Найди их и исправь. + +P.S. Для корректной работы Map в многопоточной среде, желательно пользоваться стандартной реализацией, например +ConcurrentHashMap из пакета java.util.concurrent. Но иногда требуется работа с другим типом мапы, например +LinkedHashMap и тогда предложенное решение будет как никогда кстати. + + +Требования: +1. Поле readLock должно быть инициализировано с помощью метода readLock вызванного на объекте lock. +2. Поле writeLock должно быть инициализировано с помощью метода writeLock вызванного на объекте lock. +3. В методе put должен быть вызван метод lock на объекте writeLock. +4. В методе get должен быть вызван метод lock на объекте readLock. +5. В методе put в блоке finally должен быть вызван метод unlock на объекте writeLock. +6. В методе get в блоке finally должен быть вызван метод unlock на объекте readLock. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2812/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2812/Solution.java new file mode 100644 index 0000000..8ba6de7 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2812/Solution.java @@ -0,0 +1,32 @@ +package com.javarush.task.task28.task2812; + +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/* +ShutdownNow! +*/ + +public class Solution { + public static void main(String[] args) throws InterruptedException { + ExecutorService executor = Executors.newFixedThreadPool(5); + for (int i = 1; i <= 10; i++) { + final int localId = i; + executor.submit(new Runnable() { + public void run() { + doExpensiveOperation(localId); + } + }); + } + + List list = executor.shutdownNow(); + for (Runnable task: list){ + System.out.println(task.toString()); + } + } + + private static void doExpensiveOperation(int localId) { + System.out.println(Thread.currentThread().getName() + ", localId="+localId); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task28/task2812/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task28/task2812/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..daa9f22 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task28/task2812/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,26 @@ +taskKey="com.javarush.task.task28.task2812" + +ShutdownNow! + +Разберись в чем отличие методов shutdown и shutdownNow. Выведи список всех незавершенных задач на экран. + +Должно получиться что-то вроде: +pool-1-thread-1, localId=1 +pool-1-thread-2, localId=2 +pool-1-thread-3, localId=3 +pool-1-thread-4, localId=4 +pool-1-thread-5, localId=5 +java.util.concurrent.FutureTask@7e6cbb7a was not completed +java.util.concurrent.FutureTask@7c3df479 was not completed +java.util.concurrent.FutureTask@7106e68e was not completed +java.util.concurrent.FutureTask@7eda2dbb was not completed +java.util.concurrent.FutureTask@6576fe71 was not completed + + +Требования: +1. В методе main класса Solution должен быть вызван метод shutdownNow на объекте executor. +2. В методе main класса Solution на экран должны быть выведены все задачи которые не успел выполнить executor. +3. Метод main должен быть публичным. +4. Метод main должен быть статическим. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2813/FactorialCalculator.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2813/FactorialCalculator.java new file mode 100644 index 0000000..8ad76cf --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2813/FactorialCalculator.java @@ -0,0 +1,29 @@ +package com.javarush.task.task28.task2813; + +import java.util.concurrent.Callable; + +public class FactorialCalculator implements Callable { + private final int number; + + public FactorialCalculator(int number) { + this.number = number; + } + + @Override + public Long call() throws InterruptedException { + return factorial(number); + } + + public long factorial(int number) throws InterruptedException { + if (number < 0) { + throw new IllegalArgumentException("Number must be greater than zero"); + } + long result = 1; + while (number > 1) { + Thread.sleep(1); + result = result * number; + number--; + } + return result; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task28/task2813/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task28/task2813/Solution.java new file mode 100644 index 0000000..ee4359b --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task28/task2813/Solution.java @@ -0,0 +1,31 @@ +package com.javarush.task.task28.task2813; + +import java.util.concurrent.*; + +/* +FutureTask +*/ + +public class Solution { + private static final ExecutorService threadpool = Executors.newFixedThreadPool(4); + private static final int n = 16; + + public static void main(String args[]) throws InterruptedException, ExecutionException { + FactorialCalculator task = new FactorialCalculator(n); + + System.out.println("Submitting Task ..."); + Future future = threadpool.submit(task); + System.out.println("Task was submitted successfully"); + + while (!future.isDone()) { + System.out.println("Task is not completed yet...."); + Thread.sleep(1); + } + + System.out.println("Task is completed, let's check the result"); + long factorial = (long) future.get(); + + System.out.println("Factorial of " + n + " is : " + factorial); + threadpool.shutdown(); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task28/task2813/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task28/task2813/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..6c78246 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task28/task2813/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,17 @@ +taskKey="com.javarush.task.task28.task2813" + +FutureTask + +Класс FactorialCalculator предназначен для вычисления факториала числа переданного в его конструктор в качестве +параметра. К сожалению, он реализован некорректно и тебе необходимо это исправить. + +Внимательно разбери метод main класса Solution. + + +Требования: +1. Класс FactorialCalculator должен поддерживать интерфейс Callable. +2. Метод call класса FactorialCalculator должен возвращать результат выполнения метода factorial. +3. Метод call класса FactorialCalculator должен быть публичным. +4. Поле number класса FactorialCalculator должно быть приватным. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2901/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2901/Solution.java new file mode 100644 index 0000000..98b31b6 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2901/Solution.java @@ -0,0 +1,51 @@ +package com.javarush.task.task29.task2901; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.util.List; + +/* +Рефакторинг в соответствии с Naming and Code Convention +*/ +public class Solution { + public static final String DEFAULT_FILE_NAME = "C:/tmp/file_strange_name.tmp"; + + private final String LOCAL_FILE_NAME; + private List contentAslines; + private boolean isFileLoaded; + + public Solution(String firstFileName) { + LOCAL_FILE_NAME = firstFileName == null ? DEFAULT_FILE_NAME : firstFileName; + } + + public static void main(String[] args) throws FileNotFoundException { + String fileName = Solution.class.getResource("Solution.java").getPath(); + + Solution solution = new Solution(fileName); + solution.downloadFileContent(); + if (solution.isFileLoaded()) { + System.out.println(solution.hasFileExpectedLine("public class Solution {")); //expected true + System.out.println(solution.hasFileExpectedLine(" public class Solution {")); //expected false + } + } + + public boolean isFileLoaded() { + return isFileLoaded; + } + + public void downloadFileContent() { + try { + contentAslines = Files.readAllLines((new File(LOCAL_FILE_NAME)).toPath(), Charset.defaultCharset()); + isFileLoaded = true; + } catch (IOException e) { + System.out.println("Unsuccessful. What a surprise!"); + } + } + + public boolean hasFileExpectedLine(String expectedLine) { + return contentAslines.contains(expectedLine); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task29/task2901/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task29/task2901/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..16a2d01 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task29/task2901/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,18 @@ +taskKey="com.javarush.task.task29.task2901" + +Рефакторинг в соответствии с Naming and Code Convention + +Исправить код в соответствии с Naming and Code Convention (Shift+F6 для рефакторинга). + +Подсказка: IDEA не умеет правильно переименовывать имена классов, если меняется только регистр. +Переименуй имя класса во вспомогательное имя, а потом в это же в правильном регистре. + + +Требования: +1. Переименуй константу defaultFileName в соответствии с Naming and Code Convention. +2. Переименуй метод getFileLoaded в соответствии с Naming and Code Convention. +3. Переименуй метод DownloadFileContent в соответствии с Naming and Code Convention. +4. Переименуй метод isfileexpectedline в соответствии с Naming and Code Convention. +5. Переименуй параметр expectedline метода принимающего String в соответствии с Naming and Code Convention. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2902/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2902/Solution.java new file mode 100644 index 0000000..80f7914 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2902/Solution.java @@ -0,0 +1,29 @@ +package com.javarush.task.task29.task2902; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.Path; +import java.nio.file.Paths; + +/* +Рефакторинг в соответствии с Naming and Code Convention 2 +*/ +public class Solution { + public static void main(String[] args) throws IOException, InterruptedException, URISyntaxException { + Solution solution = new Solution(); + String fileNameToBeOpenedByNotepad = solution.getAbsolutePathToDefaultTxtFile().toString(); + Process notepad = solution.getProcessStartNotepad(fileNameToBeOpenedByNotepad); + notepad.waitFor(); + } + + public Process getProcessStartNotepad(String fileName) throws IOException { + String[] cmdArray = new String[]{"notepad.exe", fileName}; + return Runtime.getRuntime().exec(cmdArray); + } + + public Path getAbsolutePathToDefaultTxtFile() throws URISyntaxException { + URI uri = Solution.class.getResource("file.txt").toURI(); + return Paths.get(uri); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2902/file.txt b/3.JavaMultithreading/src/com/javarush/task/task29/task2902/file.txt new file mode 100644 index 0000000..2fe78f4 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2902/file.txt @@ -0,0 +1,2 @@ +This file will be opened by Notepad.exe +You can change the content. \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task29/task2902/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task29/task2902/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..dea4a4d --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task29/task2902/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,18 @@ +taskKey="com.javarush.task.task29.task2902" + +Рефакторинг в соответствии с Naming and Code Convention 2 + +Исправить код в соответствии с Naming and Code Convention (Shift+F6 для рефакторинга). + + +Требования: +1. Переименуй переменную Solution типа Solution в соответствии с Naming and Code Convention. +2. Переименуй переменную file_name_to_be_opened_by_notepad типа String в соответствии с Naming and Code Convention. +3. Переименуй переменную NOTEPAD типа Process в соответствии с Naming and Code Convention. +4. Переименуй метод getprocessstartnotepad в соответствии с Naming and Code Convention. +5. Переименуй параметр FILE_NAME метода принимающего String в соответствии с Naming and Code Convention. +6. Переименуй переменную cmd_array типа String[] в соответствии с Naming and Code Convention. +7. Переименуй метод Getabsolutepathtodefaulttxtfile в соответствии с Naming and Code Convention. +8. Переименуй переменную uRi типа URI в соответствии с Naming and Code Convention. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2903/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2903/Solution.java new file mode 100644 index 0000000..2db7802 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2903/Solution.java @@ -0,0 +1,50 @@ +package com.javarush.task.task29.task2903; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ThreadLocalRandom; + +/* +И еще раз рефакторинг +*/ +public class Solution { + public static final ThreadLocalRandom RANDOM = ThreadLocalRandom.current(); + + public static void main(String[] args) { + ConcurrentMap concurrentMap = new ConcurrentHashMap<>(); + for (int i = 0; i < 100; i++) { + new Thread(getRunnable(i, concurrentMap)).start(); + } + sleepASecond(); + } + + private static void sleepASecond() { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + public static Runnable getRunnable(final int i, final ConcurrentMap concurrentMap) { + return new Runnable() { + @Override + public void run() { + final String NAME = "Thread #" + i; + int randomInt = RANDOM.nextInt(20); + String text = NAME + " вставил запись для " + randomInt; + + //previousEntry is null if it is new entry + /* instead of null - call concurrentMap.someMethodName(randomInt, text)*/ + //String previousEntry = null; + String previousEntry = concurrentMap.putIfAbsent(randomInt, text); + + if (previousEntry != null) { + System.out.println(NAME + " хочет обновить " + randomInt + ", однако уже " + previousEntry); + } else { + System.out.println(text); + } + } + }; + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task29/task2903/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task29/task2903/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..fac6a84 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task29/task2903/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,18 @@ +taskKey="com.javarush.task.task29.task2903" + +И еще раз рефакторинг + +1. Исправить код в соответствии с Naming and Code Convention (Shift+F6 для рефакторинга) +2. Просмотри методы класса ConcurrentMap. +3. В строке "String previousEntry = null;" у concurrentMap вызови метод, +который вставит пару (randomInt, text) только для ключа, которого нет в concurrentMap. +(Вызванный метод должен возвращать предыдущее значение либо null для новой пары.) + + +Требования: +1. Переименуй константу random в соответствии с Naming and Code Convention. +2. Объект, возвращаемый методом getRunnable, должен быть экземпляром анонимного класса. +3. Метод run внутри метода getRunnable должен вызывать у concurrentMap метод, вставляющий пару (randomInt, text), если в concurrentMap еще нет пары со значением ключа randomInt. +4. Метод run класса, возвращаемого методом getRunnable, должен выводить текст на экран. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2904/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2904/Solution.java new file mode 100644 index 0000000..6de6207 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2904/Solution.java @@ -0,0 +1,24 @@ +package com.javarush.task.task29.task2904; + +/* +Особенности автобоксинга +*/ +public class Solution { + private Integer[] array = new Integer[]{1, 2, 3, 4}; + + public static void main(String[] args) { + Number value1 = new Solution().getValueByIndex(5); //-1.0, class java.lang.Double expected + Number value2 = new Solution().getValueByIndex(2); //3, class java.lang.Integer expected + + System.out.println(value1 + ", " + value1.getClass().toString()); + System.out.println(value2 + ", " + value2.getClass().toString()); + } + + Number getValueByIndex(int index) { + if (index >= 0 && index < array.length) { + return array[index]; + } else { + return new Double(-1); + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task29/task2904/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task29/task2904/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..ac38684 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task29/task2904/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,15 @@ +taskKey="com.javarush.task.task29.task2904" + +Особенности автобоксинга + +Исправь ошибку в методе getValueByIndex. +Читай доп. статью про особенности автобоксинга. + + +Требования: +1. Метод getValueByIndex должен возвращать объект типа Integer из массива array, если элемент с индексом index есть в массиве. +2. Метод getValueByIndex должен возвращать объект типа Double, равный -1, если в массиве array нет элемента с индексом index. +3. Метод main не изменять. +4. Программа должна вывести две строки: "-1.0, class java.lang.Double" и "3, class java.lang.Integer". + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2905/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2905/Solution.java new file mode 100644 index 0000000..3463802 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2905/Solution.java @@ -0,0 +1,91 @@ +package com.javarush.task.task29.task2905; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.logging.Level; +import java.util.logging.Logger; + +/* +Странные ошибки О_о +*/ +public class Solution { + final int NUMBER_OF_THREADS = 3; //3 треда будет обрабатывать нашу очередь + final int MAX_BATCH_SIZE = 100; //будем вытаскивать по 100 сообщений + + private Logger logger = Logger.getLogger(Solution.class.getName()); + private BlockingQueue messageQueue = new LinkedBlockingQueue();//тут будут храниться все сообщения + + private BlockingQueue fakeDataBase = new LinkedBlockingQueue(); + + public static void main(String[] args) throws InterruptedException { + // статики во многих местах неуместны, поэтому помещаем все данные в поля класса, + // затем создаем объект и вызываем его метод + Solution solution = new Solution(); + + solution.startMessageCreating(); + solution.startMessagePersisting(); + + Thread.sleep(100); + solution.printResults(); + + Thread.sleep(100); + solution.printResults(); + + Thread.sleep(100); + solution.printResults(); + + Thread.sleep(500); + solution.printResults(); + } + + public void startMessageCreating() { + new Thread() { + @Override + public void run() { + for (int i = 0; i < 100000; i++) { + messageQueue.add(String.valueOf(i)); + } + } + }.start(); + } + + public void startMessagePersisting() { + for (int i = 0; i < NUMBER_OF_THREADS; i++) { + new Thread() { + private final Collection batch = new ArrayList(MAX_BATCH_SIZE); + + { + setDaemon(true); + } + + @Override + public void run() { + while (true) { + try { + messageQueue.drainTo(batch, MAX_BATCH_SIZE); + persistData(batch); + batch.clear(); + Thread.sleep(1); + } catch (Throwable e) { + logger.log(Level.SEVERE, "impossible to persist a batch", e); + } + } + } + }.start(); + } + } + + private void persistData(Collection batch) { + //представим, что тут мы коннектимся к базе данных, и сохраняем данные в нее + //сохранение данных по 1 записи тратит много ресурсов, поэтому делают батчем (группой по несколько) + fakeDataBase.addAll(batch); + } + + private void printResults() { + System.out.println(); + System.out.println("messageQueue size is " + messageQueue.size()); + System.out.println("fakeDataBase size is " + fakeDataBase.size()); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task29/task2905/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task29/task2905/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..d3a1065 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task29/task2905/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,17 @@ +taskKey="com.javarush.task.task29.task2905" + +Странные ошибки О_о + +Исправь 2 ошибки: +1) возникновение исключения +2) подвисание +Сделай минимальные изменения. + + +Требования: +1. Метод startMessageCreating должен без зависаний добавлять в messageQueue 100000 элементов. +2. Исправь ошибку в строке "messageQueue.drainTo(messageQueue, MAX_BATCH_SIZE);". +3. Метод main не должен зависать. +4. Вывод программы должен показывать, что все сообщения из messageQueue были перенесены в fakeDataBase. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2906/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2906/Solution.java new file mode 100644 index 0000000..70ca5db --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2906/Solution.java @@ -0,0 +1,20 @@ +package com.javarush.task.task29.task2906; + +/* +Особенности автобоксинга - 2 +*/ +public class Solution { + public static void main(String[] args) { + Integer a = getValue(Boolean.TRUE, Boolean.TRUE); //100 expected + Integer b = getValue(Boolean.FALSE, Boolean.TRUE); //200 expected + Integer c = getValue(Boolean.FALSE, Boolean.FALSE); //null expected + + System.out.println(a); + System.out.println(b); + System.out.println(c); + } + + public static Integer getValue(boolean first, boolean second) { + return first ? Integer.valueOf(100) : second ? Integer.valueOf(200) : null ; + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task29/task2906/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task29/task2906/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..5885806 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task29/task2906/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,16 @@ +taskKey="com.javarush.task.task29.task2906" + +Особенности автобоксинга - 2 + +Исправь ошибку реализации, приводящую к NullPointerException, в методе getValue. +Читай доп. статью про особенности автобоксинга. + + +Требования: +1. Реализация метод getValue должна использовать тернарный оператор. +2. Метод getValue не должен кидать исключений при любых значениях параметров first и second. +3. Метод getValue должен вернуть 100, если в него передать Boolean.TRUE и Boolean.TRUE. +4. Метод getValue должен вернуть 200, если в него передать Boolean.FALSE и Boolean.TRUE. +5. Метод getValue должен вернуть null, если в него передать Boolean.FALSE и Boolean.FALSE. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2907/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2907/Solution.java new file mode 100644 index 0000000..108c8e3 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2907/Solution.java @@ -0,0 +1,16 @@ +package com.javarush.task.task29.task2907; + +import java.math.BigDecimal; + +/* +Этот странный BigDecimal +*/ +public class Solution { + public static void main(String[] args) { + System.out.println(getValue(1.1d, 1.2d)); + } + + public static BigDecimal getValue(double v1, double v2) { + return new BigDecimal(String.valueOf(v1)).add(new BigDecimal(String.valueOf(v2))); + } +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task29/task2907/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task29/task2907/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..97bf8cf --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task29/task2907/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,16 @@ +taskKey="com.javarush.task.task29.task2907" + +Этот странный BigDecimal + +Исправь ошибку реализации, приводящую к погрешности вычисления, в методе getValue. +Сигнатуру метода не менять. Округление не использовать. +Читай доп. статью про особенности автобоксинга. + + +Требования: +1. Метод getValue должен создавать два объекта типа BigDecimal. +2. Метод getValue должен вызывать метод add у созданного объекта BigDecimal. +3. Метод getValue НЕ должен использовать метод round. +4. Метод getValue должен возвращать результат без погрешности. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2908/CacheComputeManager.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2908/CacheComputeManager.java new file mode 100644 index 0000000..8f15e85 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2908/CacheComputeManager.java @@ -0,0 +1,46 @@ +package com.javarush.task.task29.task2908; + +import java.util.concurrent.*; + +/* Argument and Value are generic types*/ +public class CacheComputeManager implements Computable { + private final ConcurrentHashMap> cache = new ConcurrentHashMap<>(); + private final Computable computable; + + public CacheComputeManager(Computable computable) { + this.computable = computable; + } + + @Override + public Value compute(final Argument arg) throws InterruptedException { + Future f = cache.get(arg); + if (f == null) { + FutureTask ft = createFutureTaskForNewArgumentThatHaveToComputeValue(arg); + cache.putIfAbsent(arg, ft); + f = ft; + ft.run(); + System.out.print(arg + " will be cached "); + } else { + System.out.print(arg + " taken from cache "); + } + try { + return f.get(); + } catch (CancellationException e) { + cache.remove(arg, f); + } catch (ExecutionException e) { + throw new RuntimeException(e.getCause()); + } + return null; + } + + public FutureTask createFutureTaskForNewArgumentThatHaveToComputeValue(final Argument arg) { + + FutureTask task = new FutureTask(new Callable() { + @Override + public Value call() throws Exception { + return computable.compute(arg); + } + }); + return task; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2908/Computable.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2908/Computable.java new file mode 100644 index 0000000..9077d8c --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2908/Computable.java @@ -0,0 +1,6 @@ +package com.javarush.task.task29.task2908; + +/* Argument and Value are generic types*/ +public interface Computable { + Value compute(Argument argument) throws InterruptedException; +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2908/Copyright.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2908/Copyright.java new file mode 100644 index 0000000..1848490 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2908/Copyright.java @@ -0,0 +1,46 @@ +package com.javarush.task.task29.task2908; + +public class Copyright implements Computable { + @Override + public String compute(Period period) throws InterruptedException { + return "All rights reserved (c) " + period.firstYear + "-" + period.secondYear; + } + + public static class Period { + int firstYear; + int secondYear; + + public Period(int firstYear, int secondYear) { + this.firstYear = firstYear; + this.secondYear = secondYear; + } + + @Override + public String toString() { + return "Period{" + + "firstYear=" + firstYear + + ", secondYear=" + secondYear + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Period)) return false; + + Period period = (Period) o; + + if (firstYear != period.firstYear) return false; + if (secondYear != period.secondYear) return false; + + return true; + } + + @Override + public int hashCode() { + int result = firstYear; + result = 31 * result + secondYear; + return result; + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2908/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2908/Solution.java new file mode 100644 index 0000000..fab3e92 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2908/Solution.java @@ -0,0 +1,42 @@ +package com.javarush.task.task29.task2908; + +/* +Кеширование +*/ +public class Solution { + public static void main(String[] args) throws InterruptedException { + //////////////first example/////////////////// + Square square = new Square(); + CacheComputeManager manager = new CacheComputeManager(square); + + for (int i = 0; i < 8; i++) { + int j = i % 4; + Integer result = manager.compute(j); + System.out.format("%d * %d = %d\n", j, j, result); + } + + /* output + 0 will be cached 0 * 0 = 0 + 1 will be cached 1 * 1 = 1 + 2 will be cached 2 * 2 = 4 + 3 will be cached 3 * 3 = 9 + 0 taken from cache 0 * 0 = 0 + 1 taken from cache 1 * 1 = 1 + 2 taken from cache 2 * 2 = 4 + 3 taken from cache 3 * 3 = 9 + */ + + //////////////second example/////////////////// + Copyright copyright = new Copyright(); + CacheComputeManager manager2 = new CacheComputeManager(copyright); + System.out.println(manager2.compute(new Copyright.Period(3012, 3147))); + System.out.println(manager2.compute(new Copyright.Period(3012, 3146))); + System.out.println(manager2.compute(new Copyright.Period(3012, 3147))); + + /* output + Period{firstYear=3012, secondYear=3147} will be cached All rights reserved (c) 3012-3147 + Period{firstYear=3012, secondYear=3146} will be cached All rights reserved (c) 3012-3146 + Period{firstYear=3012, secondYear=3147} taken from cache All rights reserved (c) 3012-3147 + */ + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2908/Square.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2908/Square.java new file mode 100644 index 0000000..ac4c227 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2908/Square.java @@ -0,0 +1,9 @@ +package com.javarush.task.task29.task2908; + +public class Square implements Computable { + @Override + public Integer compute(Integer integer) throws InterruptedException { + int val = integer.intValue(); + return val * val; + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task29/task2908/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task29/task2908/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..5d94be6 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task29/task2908/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,15 @@ +taskKey="com.javarush.task.task29.task2908" + +Кеширование + +В CacheComputeManager реализуй логику пустого метода. +Догадайся, что он должен делать по названию метода и по логике класса. + + +Требования: +1. Метод createFutureTaskForNewArgumentThatHaveToComputeValue должен создавать и возвращать объект типа FutureTask. +2. В методе createFutureTaskForNewArgumentThatHaveToComputeValue должен создаваться объект анонимного класса, реализующего интерфейс Callable. +3. Внутри метода createFutureTaskForNewArgumentThatHaveToComputeValue должна встречаться строка "return computable.compute(arg);". +4. Программа должна выводить текст указанный в комментариях в классе Solution. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2910/Constants.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2910/Constants.java new file mode 100644 index 0000000..2b323ef --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2910/Constants.java @@ -0,0 +1,12 @@ +package com.javarush.task.task29.task2910; + +import java.math.BigDecimal; + +public class Constants { + public static final Double RACE_LENGTH = new Double(20.0); + public static final int NUMBER_OF_FIRE_LINES = 4; + public static final int PENALTY_TIME_PER_ONE_MISS = 20; + public static final BigDecimal MIN_CHANCE_TO_HIT_IN_TARGET = new BigDecimal("0.815"); + public static final BigDecimal MAX_CHANCE_TO_HIT_IN_TARGET = new BigDecimal("0.900"); + public static final int SPORTSMAN_COUNT = 30; +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2910/Game.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2910/Game.java new file mode 100644 index 0000000..1e57471 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2910/Game.java @@ -0,0 +1,61 @@ +package com.javarush.task.task29.task2910; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +import static com.javarush.task.task29.task2910.Constants.*; + +public class Game { + private List members; + Sportsman controlSportsman; + + public Game() { + initializeControlSportsman(); + members = new ArrayList<>(); + for (int i = 0; i < SPORTSMAN_COUNT; i++) { + members.add(new Sportsman(i + 1)); + } + } + + private void initializeControlSportsman() { + controlSportsman = new Sportsman(0); + controlSportsman.setAverageSpeed(new BigDecimal(20.)); + controlSportsman.setChanceToHit(MAX_CHANCE_TO_HIT_IN_TARGET); + controlSportsman.setCountHitOutTarget(2); + controlSportsman.setResultTime(new BigDecimal("3640.00")); + System.out.println("РЕЗУЛЬТАТ КОНТРОЛЬНО СПОРТСМЕНА:"); + controlSportsman.printResultInfo(); + } + + public void startCompetition() { + for (int i = 0; i < members.size(); i++) { + members.get(i).calculateNumberOfMiss(); + BigDecimal timeToRace = controlSportsman.getResultTime().subtract(BigDecimal.valueOf(members.get(i).getCountHitOutTarget() * PENALTY_TIME_PER_ONE_MISS)); + members.get(i).setAverageSpeed(new BigDecimal(RACE_LENGTH / (timeToRace.doubleValue() / 3600)).setScale(4, BigDecimal.ROUND_HALF_UP)); + members.get(i).calculateFullTime(); + } + } + + public void printAllResults() { + for (int i = 0; i < members.size(); i++) { + members.get(i).printResultInfo(); + } + } + + public void printSportsmanWithEqualTime() { + for (Sportsman sportsman : getSportsmanWithEqualTime()) { + sportsman.printResultInfo(); + } + } + + private List getSportsmanWithEqualTime() { + List result = new ArrayList<>(); + for (int i = 0; i < members.size(); i++) { + if (members.get(i).getResultTime().equals(controlSportsman.getResultTime())) { + result.add((members.get(i))); + } + } + return result; + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2910/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2910/Solution.java new file mode 100644 index 0000000..e0b9987 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2910/Solution.java @@ -0,0 +1,24 @@ +package com.javarush.task.task29.task2910; + +/* +Это архаичное слово "Биатлон" +*/ + +public class Solution { + + public static void main(String[] args) { + Game game = new Game(); + printDelimiter(); + game.startCompetition(); + System.out.println("\n\nВСЕ РЕЗУЛЬТАТЫ:"); + game.printAllResults(); + printDelimiter(); + System.out.println("\n\nСПОРТСМЕНЫ С ТАКИМ ЖЕ ИТОГОВЫМ ВРЕМЕНЕМ, КАК У КОНТРОЛЬНОГО СПОРТСМЕНА:"); + game.printSportsmanWithEqualTime(); + printDelimiter(); + } + + private static void printDelimiter() { + System.out.println("================================================================================================="); + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2910/Sportsman.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2910/Sportsman.java new file mode 100644 index 0000000..7ebb84b --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2910/Sportsman.java @@ -0,0 +1,74 @@ +package com.javarush.task.task29.task2910; + +import java.math.BigDecimal; +import java.util.concurrent.ThreadLocalRandom; + +import static com.javarush.task.task29.task2910.Constants.*; + +public class Sportsman { + + private BigDecimal chanceToHit; + private BigDecimal averageSpeed; + private BigDecimal resultTime = new BigDecimal("0."); + private int number; + private int countHitOutTarget = 0; + + public Sportsman(int number) { + this.number = number; + chanceToHit = BigDecimal.valueOf(ThreadLocalRandom.current().nextDouble(MIN_CHANCE_TO_HIT_IN_TARGET.doubleValue(), MAX_CHANCE_TO_HIT_IN_TARGET.doubleValue())); + } + + public void calculateFullTime() { + resultTime = resultTime.add(BigDecimal.valueOf(countHitOutTarget * PENALTY_TIME_PER_ONE_MISS)); + resultTime = resultTime.add(calculateTimeToRace()); + } + + private BigDecimal calculateTimeToRace() { + return new BigDecimal(RACE_LENGTH / averageSpeed.doubleValue() * 3600).setScale(2, BigDecimal.ROUND_HALF_UP); + } + + public void calculateNumberOfMiss() { + for (int i = 0; i < NUMBER_OF_FIRE_LINES * 5; i++) { + double temp = Math.random(); + if (temp < (1 - chanceToHit.doubleValue())) { + countHitOutTarget++; + } + } + } + + public void setAverageSpeed(BigDecimal averageSpeed) { + this.averageSpeed = averageSpeed.setScale(4, BigDecimal.ROUND_HALF_UP); + } + + public BigDecimal getResultTime() { + return resultTime; + } + + public int getNumber() { + return number; + } + + public void setNumber(int number) { + this.number = number; + } + + public int getCountHitOutTarget() { + return countHitOutTarget; + } + + public void setCountHitOutTarget(int countHitOutTarget) { + this.countHitOutTarget = countHitOutTarget; + } + + public void setChanceToHit(BigDecimal chanceToHit) { + this.chanceToHit = chanceToHit; + } + + public void setResultTime(BigDecimal resultTime) { + this.resultTime = resultTime; + } + + public void printResultInfo() { + System.out.printf("Спортсмен № %02d: Время - %6.2f секунд. Средняя скорость - %2.4f км/час. Количество промахов %d\n", number, resultTime.doubleValue(), averageSpeed, countHitOutTarget); + } +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task29/task2910/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task29/task2910/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..b67d5a6 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task29/task2910/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,38 @@ +taskKey="com.javarush.task.task29.task2910" + +Это архаичное слово "Биатлон" + +Амиго, представляешь, в 21 веке существовал такой вид спорта – биатлон. Люди ездили на лыжах и стреляли на +подготовленных площадках по мишеням. За одну серию стрельбы нужно было закрыть 5 мишеней. Стрельбы +происходили как стоя, так и лежа, но не будем вдаваться в подробности. У лучших представителей рода +человеческого средняя точность стрельбы достигала 90%, у крепких середнячков – 81,5%. +Я написал программу, которая создает соревнование, добавляет в него 30 спортсменов-биатлонистов. Каждому из +них случайным образом выставляется точность (в диапазоне от 0,815 до 0,900). Штраф за каждый промах – плюс +20 секунд к результату. Еще у соревнования задается количество огневых рубежей – 4 и дистанция, которую +биатлонисты должны преодолеть – 20 км. +Так же я создал контрольного спортсмена, у которого захардкожены показатели: +Скорость: 20 км/час; +Вероятность попадания: 0,900 (90%); +Количество промахов: 2 (Всего нужно попасть 20 раз. При точности 90 процентов ожидается 2 промаха); +Нужно проехать 20 км со скоростью 20 км/час. Необходимое время - 1 час, то есть 3600 секунд. +Время гонки (с учетом штрафных секунд): 3600 + 2 * 20 = 3640 секунд. +Я хочу определить, с какой скоростью должен ехать каждый спортсмен, при его случайном количестве промахов, +чтобы результат в секундах был такой же, как и у контрольного спортсмена. В начале я вывожу результат +контрольного спортсмена, потом все результаты. В конце я вывожу всех спортсменов, у которых время такое же, +как и у контрольного спортсмена. У некоторых спортсменов за счет округления итоговое время отличается на доли +секунды. Такие нам не нужны. У остальных время гонки ровно 3640 секунд, как и у контрольного спортсмена, но +они не выводятся в секции "СПОРТСМЕНЫ С ТАКИМ ЖЕ ИТОГОВЫМ ВРЕМЕНЕМ, КАК У КОНТРОЛЬНОГО СПОРТСМЕНА:". + +Твоя задача: сделать одно изменение в коде, чтобы исправить найденный баг. +Обрати внимание: все округления правильные, и новых добавлять не нужно! + + +Требования: +1. Запрещено изменять типы данных констант. +2. Вывод на экран в секции "СПОРТСМЕНЫ С ТАКИМ ЖЕ ИТОГОВЫМ ВРЕМЕНЕМ, КАК У КОНТРОЛЬНОГО СПОРТСМЕНА:" должен содержать всех спортсменов, у которых такое же время, как и у контрольного спортсмена. +3. Сделай одно изменение в классе Game. +4. Класс Constants не изменяй. +5. Класс Solution не изменяй. +6. Класс Sportsman не изменяй. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2911/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2911/Solution.java new file mode 100644 index 0000000..9301442 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2911/Solution.java @@ -0,0 +1,56 @@ +package com.javarush.task.task29.task2911; + +import java.util.Random; +import java.util.Scanner; + +/* +И еще раз рефакторинг +*/ + +public class Solution { + public static boolean flagWin = false; + + public static void main(String[] args) { + new Solution().runGame(); + } + + private void runGame() { + Random random = new Random(); + int secret = random.nextInt(1000); + int tryNumber = -1; + Scanner scanner = new Scanner(System.in); + for (int i = 1; i <= 10; i++) { + System.out.printf("Попытка %d - вводи число: ", i); + tryNumber = scanner.nextInt(); + if (tryNumber < secret) + if (i < 10) + System.out.println("Загаданное число больше"); + if (tryNumber > secret) + if (i < 10) + System.out.println("Загаданное число меньше"); + if (tryNumber == secret) { + i = stopGame(); + flagWin = true; + } + } + if (flagWin) + printCongratulations(tryNumber); + else + printUpset(); + } + + private void printCongratulations(int number) { + System.out.println(); + System.out.println("Ты угадал!"); + System.out.println("Загаданное число: " + number); + } + + private void printUpset() { + System.out.println(); + System.out.println("Ты проиграл!"); + } + + private int stopGame() { + return 10; + } +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task29/task2911/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task29/task2911/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..531a412 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task29/task2911/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,20 @@ +taskKey="com.javarush.task.task29.task2911" + +И еще раз рефакторинг + +Задается целое число от 0 до 1000 включительно случайным образом. Пользователь вводит с клавиатуры число. +Программа отвечает, введенное число больше или меньше загаданного. Если за 10 попыток пользователь программы +угадывает число - программа выводит: +"Ты угадал!" +"Загаданное число: [number]", +иначе "Ты проиграл!". +Исправь одну ошибку, чтобы код выполнял описанные действия. + + +Требования: +1. Если за 10 попыток не введено правильного числа - программа должна вывести на экран "Ты проиграл!". +2. Если введено неправильное число, флаг boolean flagWin не должен иметь значение true. +3. Не изменяй сигнатуры методов. +4. Нужно сделать одно изменение в правильном месте программы. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2912/AbstractLogger.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/AbstractLogger.java new file mode 100644 index 0000000..4422c63 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/AbstractLogger.java @@ -0,0 +1,31 @@ +package com.javarush.task.task29.task2912; + +/** + * Created by ArchMage on 06.04.17. + */ +public abstract class AbstractLogger implements Logger { + int level; + Logger next; + + public AbstractLogger(int level) { + this.level = level; + } + + public void inform(String message, int level) { + if (this.level <= level) { + info(message); + } + if (next != null) { + next.inform(message, level); + } + } + + public void setNext(Logger next) { + this.next = next; + } + + public void info(String message) { + + }; + +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2912/ConsoleLogger.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/ConsoleLogger.java new file mode 100644 index 0000000..07c09cf --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/ConsoleLogger.java @@ -0,0 +1,13 @@ +package com.javarush.task.task29.task2912; + +public class ConsoleLogger extends AbstractLogger { + + public ConsoleLogger(int level) { + super(level); + } + + @Override + public void info(String message) { + System.out.println("Logging to console: " + message); + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2912/FileLogger.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/FileLogger.java new file mode 100644 index 0000000..cc10544 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/FileLogger.java @@ -0,0 +1,13 @@ +package com.javarush.task.task29.task2912; + +public class FileLogger extends AbstractLogger { + + public FileLogger(int level) { + super(level); + } + + @Override + public void info(String message) { + System.out.println("Logging to file: " + message); + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2912/Level.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/Level.java new file mode 100644 index 0000000..1ca38f5 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/Level.java @@ -0,0 +1,8 @@ +package com.javarush.task.task29.task2912; + +public class Level { + public static final int INFO = 100; + public static final int WARN = 200; + public static final int ERROR = 300; + public static final int FATAL = 400; +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2912/Logger.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/Logger.java new file mode 100644 index 0000000..4ed8bce --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/Logger.java @@ -0,0 +1,9 @@ +package com.javarush.task.task29.task2912; + +public interface Logger { + void inform(String message, int level); + + void setNext(Logger next); + + void info(String message); +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2912/PhoneLogger.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/PhoneLogger.java new file mode 100644 index 0000000..a1f2076 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/PhoneLogger.java @@ -0,0 +1,13 @@ +package com.javarush.task.task29.task2912; + +public class PhoneLogger extends AbstractLogger { + + public PhoneLogger(int level) { + super(level); + } + + @Override + public void info(String message) { + System.out.println("Call to director: " + message); + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2912/SmsLogger.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/SmsLogger.java new file mode 100644 index 0000000..3a09e31 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/SmsLogger.java @@ -0,0 +1,13 @@ +package com.javarush.task.task29.task2912; + +public class SmsLogger extends AbstractLogger { + + public SmsLogger(int level) { + super(level); + } + + @Override + public void info(String message) { + System.out.println("Send sms to CEO: " + message); + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2912/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/Solution.java new file mode 100644 index 0000000..0c2630b --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/Solution.java @@ -0,0 +1,23 @@ +package com.javarush.task.task29.task2912; + +/* +Рефакторинг паттерна Chain of Responsibility +*/ + +public class Solution { + public static void main(String[] args) { + Logger logger3 = new PhoneLogger(Level.FATAL); + Logger logger2 = new SmsLogger(Level.ERROR); + Logger logger1 = new ConsoleLogger(Level.WARN); + Logger logger0 = new FileLogger(Level.INFO); + + logger3.setNext(logger2); + logger2.setNext(logger1); + logger1.setNext(logger0); + + logger3.inform("All OK", Level.INFO); + logger3.inform("We find a bug", Level.WARN); + logger3.inform("Database connection error", Level.ERROR); + logger3.inform("System shut down", Level.FATAL); + } +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task29/task2912/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..a299a88 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task29/task2912/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,29 @@ +taskKey="com.javarush.task.task29.task2912" + +Рефакторинг паттерна Chain of Responsibility + +Есть программа, в которой реализована система логирования по принципу: +- если событие уровня FATAL - происходит звонок директору, отправляется СМС-сообщение CEO, выводится +сообщение в консоль, происходит логирование в файл; +- если событие уровня ERROR - отправляется СМС-сообщение CEO, выводится сообщение в консоль, происходит +логирование в файл; +- если событие уровня WARN - выводится сообщение в консоль, происходит логирование в файл; +- если событие уровня INFO - происходит логирование в файл. + +В программе реализован паттерн "цепочка ответственности". Изучи его внимательно. В классах FileLogger, +ConsoleLogger, SmsLogger, PhoneLogger есть много повторяющегося кода. Подними весь повторяющийся код в +абстрактный класс AbstractLogger. +Подъемом в рефакторинге называется перенос полей, методов, конструкторов из всех наследников в одного общего +предка. Из наследников, при этом, удаляется код, который перенесен в класс предка. + +Логика работы программы не должна измениться. + + +Требования: +1. Класс AbstractLogger должен быть абстрактным. +2. Класс AbstractLogger должен поддерживать интерфейс Logger. +3. Необходимо поднять поля level и next в класс AbstractLogger. +4. Необходимо поднять методы setNext(Logger) и inform(String, int) в класс AbstractLogger. +5. Вывод программы должен остаться неизменным. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task29/task2913/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task29/task2913/Solution.java new file mode 100644 index 0000000..d956bbd --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task29/task2913/Solution.java @@ -0,0 +1,41 @@ +package com.javarush.task.task29.task2913; + +import java.util.Random; + +/* +Замена рекурсии +*/ + +public class Solution { + private static int numberA; + private static int numberB; + + + public static String getAllNumbersBetween(int a, int b){ + String result = null; + for (int i = 0; i <= Math.abs(a - b); i++) { + if (a > b) { + if (i == 0) { + result = "" + a; + } else { + result = result + " " + (a - i); + } + } else { + if (i == 0) { + result = "" + a; + } else { + result = result + " " + (a + i); + } + } + } + return result; + } + + public static void main(String[] args) { + Random random = new Random(); + numberA = random.nextInt() % 1_000; + numberB = random.nextInt() % 10_000; + System.out.println(getAllNumbersBetween(numberA, numberB)); + System.out.println(getAllNumbersBetween(numberB, numberA)); + } +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task29/task2913/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task29/task2913/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..7b9a8f1 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task29/task2913/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,21 @@ +taskKey="com.javarush.task.task29.task2913" + +Замена рекурсии + +В программе случайным образом генерируются два целых числа A и В. Нужно вывести все целые числа от A до B +включительно, в порядке возрастания, если A меньше B, или в порядке убывания в противном случае. + +Задача реализована с использованием рекурсии. +Иногда в результате работы программы получаем Exception in thread "main" java.lang.StackOverflowError. + +Твоя задача: перепиши код без использования рекурсии. +Метод recursion переименуй на getAllNumbersBetween. + + +Требования: +1. Метод recursion необходимо переименовать на getAllNumbersBetween. +2. Ни в одном методе класса Solution не должно быть рекурсивных вызовов. +3. В конце строчки вывода последовательности чисел не должно быть пробела. +4. Логика работы программы должна остаться прежней. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3001/Number.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3001/Number.java new file mode 100644 index 0000000..d01e38d --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3001/Number.java @@ -0,0 +1,27 @@ +package com.javarush.task.task30.task3001; + +public class Number { + private NumerationSystem numerationSystem; + private String digit; + + public Number(NumerationSystem numerationSystem, String digit) { + this.numerationSystem = numerationSystem; + this.digit = digit; + } + + public NumerationSystem getNumerationSystem() { + return numerationSystem; + } + + public String getDigit() { + return digit; + } + + @Override + public String toString() { + return "Number{" + + "numerationSystem=" + numerationSystem + + ", digit='" + digit + '\'' + + '}'; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3001/NumerationSystem.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3001/NumerationSystem.java new file mode 100644 index 0000000..7d60816 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3001/NumerationSystem.java @@ -0,0 +1,5 @@ +package com.javarush.task.task30.task3001; + +public interface NumerationSystem { + int getNumerationSystemIntValue(); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3001/NumerationSystemType.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3001/NumerationSystemType.java new file mode 100644 index 0000000..5d492c1 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3001/NumerationSystemType.java @@ -0,0 +1,20 @@ +package com.javarush.task.task30.task3001; + +public enum NumerationSystemType implements NumerationSystem { + _16, + _12, + _10, + _9, + _8, + _7, + _6, + _5, + _4, + _3, + _2; + + @Override + public int getNumerationSystemIntValue() { + return Integer.parseInt(this.name().substring(1)); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3001/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3001/Solution.java new file mode 100644 index 0000000..725d839 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3001/Solution.java @@ -0,0 +1,126 @@ +package com.javarush.task.task30.task3001; + +import java.math.BigInteger; +import java.util.HashMap; +import java.util.Map; + +/* +Конвертер систем счислений +*/ +public class Solution { + public static void main(String[] args) { + Number number = new Number(NumerationSystemType._10, "6"); + Number result = convertNumberToOtherNumerationSystem(number, NumerationSystemType._2); + System.out.println(result); //expected 110 + + number = new Number(NumerationSystemType._16, "6df"); + result = convertNumberToOtherNumerationSystem(number, NumerationSystemType._8); + System.out.println(result); //expected 3337 + + /*Number number = new Number(NumerationSystemType._2, "1101001000000001100001001110110111111100110010101000100111011011011001001011001100011001100000111101111"); + Number result = convertNumberToOtherNumerationSystem(number, NumerationSystemType._3); + System.out.println(result); + number = new Number(NumerationSystemType._2, "1101001000000001100001001110110111111100110010101000100111011011011001001011001100011001100000111101111"); + result = convertNumberToOtherNumerationSystem(number, NumerationSystemType._4); + System.out.println(result); + number = new Number(NumerationSystemType._2, "1101001000000001100001001110110111111100110010101000100111011011011001001011001100011001100000111101111"); + result = convertNumberToOtherNumerationSystem(number, NumerationSystemType._5); + System.out.println(result); + number = new Number(NumerationSystemType._2, "1101001000000001100001001110110111111100110010101000100111011011011001001011001100011001100000111101111"); + result = convertNumberToOtherNumerationSystem(number, NumerationSystemType._6); + System.out.println(result); + number = new Number(NumerationSystemType._2, "1101001000000001100001001110110111111100110010101000100111011011011001001011001100011001100000111101111"); + result = convertNumberToOtherNumerationSystem(number, NumerationSystemType._7); + System.out.println(result); + number = new Number(NumerationSystemType._2, "1101001000000001100001001110110111111100110010101000100111011011011001001011001100011001100000111101111"); + result = convertNumberToOtherNumerationSystem(number, NumerationSystemType._8); + System.out.println(result); + number = new Number(NumerationSystemType._2, "1101001000000001100001001110110111111100110010101000100111011011011001001011001100011001100000111101111"); + result = convertNumberToOtherNumerationSystem(number, NumerationSystemType._9); + System.out.println(result); + number = new Number(NumerationSystemType._2, "1101001000000001100001001110110111111100110010101000100111011011011001001011001100011001100000111101111"); + result = convertNumberToOtherNumerationSystem(number, NumerationSystemType._10); + System.out.println(result); + number = new Number(NumerationSystemType._2, "1101001000000001100001001110110111111100110010101000100111011011011001001011001100011001100000111101111"); + result = convertNumberToOtherNumerationSystem(number, NumerationSystemType._12); + System.out.println(result); + number = new Number(NumerationSystemType._2, "1101001000000001100001001110110111111100110010101000100111011011011001001011001100011001100000111101111"); + result = convertNumberToOtherNumerationSystem(number, NumerationSystemType._16); + System.out.println(result);*/ + } + + public static Number convertNumberToOtherNumerationSystem(Number number, NumerationSystem expectedNumerationSystem) { + + BigInteger tempNumber = new BigInteger(number.getDigit(), number.getNumerationSystem().getNumerationSystemIntValue()); + + return new Number(expectedNumerationSystem, tempNumber.toString(expectedNumerationSystem.getNumerationSystemIntValue())); + + // Собственная реализация для небольших чисел + + /*String digits = number.getDigit().toLowerCase(); + int sourceNumSystem = number.getNumerationSystem().getNumerationSystemIntValue(); + Alphabet alphabet = new Alphabet(); + Map map = alphabet.getMap(); + int power = 1; + int decimalNumber = 0; + boolean isMinus = false; + for (int i = digits.length() - 1; i >= 0; i--){ + if (i == 0 && "-".equals(String.valueOf(digits.charAt(i)))) { + isMinus = true; + break; + } + Integer value = map.get(digits.charAt(i)); + //int value = map.get(digits.charAt(i)); + if (value == null || value >= sourceNumSystem) { throw new NumberFormatException(); } + if (power != 0) { + decimalNumber += value * power; + } else { decimalNumber += value; } + power *= sourceNumSystem; + } + + StringBuilder convertedNumberDigits = new StringBuilder(); + while (decimalNumber != 0) { + int digitValue = decimalNumber % expectedNumerationSystem.getNumerationSystemIntValue(); + convertedNumberDigits.append(alphabet.getByValue(digitValue)); + decimalNumber /= expectedNumerationSystem.getNumerationSystemIntValue(); + } + if (isMinus) { convertedNumberDigits.append("-"); } + convertedNumberDigits = convertedNumberDigits.reverse(); + return new Number(expectedNumerationSystem, convertedNumberDigits.toString());*/ + } + + // Собственная реализация для небольших чисел + /*private static class Alphabet{ + private Map map = new HashMap<>(); + + public Alphabet(){ + map.put('0', 0); + map.put('1', 1); + map.put('2', 2); + map.put('3', 3); + map.put('4', 4); + map.put('5', 5); + map.put('6', 6); + map.put('7', 7); + map.put('8', 8); + map.put('9', 9); + map.put('a', 10); + map.put('b', 11); + map.put('c', 12); + map.put('d', 13); + map.put('e', 14); + map.put('f', 15); + } + + public Map getMap() { + return map; + } + + public Character getByValue(int value){ + for (Map.Entry entry : map.entrySet()){ + if (entry.getValue().equals(value)) { return entry.getKey(); } + } + return null; + } + }*/ +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task30/task3001/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task30/task3001/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..fef2ef0 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task30/task3001/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,19 @@ +taskKey="com.javarush.task.task30.task3001" + +Конвертер систем счислений + +Реализуй логику метода convertNumberToOtherNumerationSystem, который должен переводить число number.getDigit(). +из одной системы счисления(numerationSystem) в другую (expectedNumerationSystem). +Брось NumberFormatException, если переданное число некорректно, например, число "120" с системой счисления 2. +Валидация для - number.getDigit() - целое не отрицательное. +Метод main не участвует в тестировании. + + +Требования: +1. Метод convertNumberToOtherNumerationSystem (Number, NumerationSystem), возвращающий тип Number, должен существовать. +2. Должно бросаться исключение NumberFormatException, если переданное число некорректно в заданной системе счисления. +3. Необходимо корректно реализовать метод convertNumberToOtherNumerationSystem - перевод числа в указанную систему счисления. +4. Enum NumerationSystemType должен поддерживать интерфейс NumerationSystem. +5. В enum-е NumerationSystemType должно присутствовать 11 значений оснований систем счисления. Основания: 2, 3, 4, 5, 6, 7, 8, 9, 10, 12 и 16. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3002/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3002/Solution.java new file mode 100644 index 0000000..234e9bb --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3002/Solution.java @@ -0,0 +1,29 @@ +package com.javarush.task.task30.task3002; + +/* +Осваиваем методы класса Integer +*/ +public class Solution { + + public static void main(String[] args) { + System.out.println(convertToDecimalSystem("0x16")); //22 + System.out.println(convertToDecimalSystem("012")); //10 + System.out.println(convertToDecimalSystem("0b10")); //2 + System.out.println(convertToDecimalSystem("62")); //62 + } + + public static String convertToDecimalSystem(String s) { + //напишите тут ваш код + if (s.length() > 1 && "0".equals(String.valueOf(s.charAt(0)))) { + if ("x".equals(String.valueOf(s.charAt(1)))) { + s = String.valueOf(Integer.parseInt(s.substring(2), 16)); + }else if ("b".equals(String.valueOf(s.charAt(1)))){ + s = String.valueOf(Integer.parseInt(s.substring(2), 2)); + }else { + s = String.valueOf(Integer.parseInt(s, 8)); + } + } + + return s; + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task30/task3002/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task30/task3002/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..01edae3 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task30/task3002/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,16 @@ +taskKey="com.javarush.task.task30.task3002" + +Осваиваем методы класса Integer + +Используя метод Integer.parseInt(String, int) реализуй логику метода convertToDecimalSystem, +который должен переводить переданную строку в десятичное число и возвращать его в виде строки. + + +Требования: +1. Метод convertToDecimalSystem (String), возвращающий String, должен существовать. +2. Метод convertToDecimalSystem (String), возвращающий String, должен иметь модификаторы доступа: public, static. +3. Метод convertToDecimalSystem (String), возвращающий String, должен переводить переданную строку в десятичное число и возвращать его в виде строки. +4. Метод convertToDecimalSystem (String) должен вызывать метод Integer.parseInt(String, int). +5. Метод main (String[]), возвращающий void, должен иметь модификаторы доступа: public, static. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3003/Consumer.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3003/Consumer.java new file mode 100644 index 0000000..90ba2b5 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3003/Consumer.java @@ -0,0 +1,29 @@ +package com.javarush.task.task30.task3003; + +import java.util.concurrent.TransferQueue; + +/** + * Created by ArchMage on 02.05.17. + */ +public class Consumer implements Runnable { + private TransferQueue queue; + + public Consumer(TransferQueue queue) { + this.queue = queue; + } + + @Override + public void run() { + try { + Thread.sleep(450); + while (true) { + ShareItem item = queue.take(); + System.out.format("Processing %s\r\n", item.toString()); + + } + } catch (InterruptedException e) { + return; + } + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3003/Producer.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3003/Producer.java new file mode 100644 index 0000000..a87ec87 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3003/Producer.java @@ -0,0 +1,33 @@ +package com.javarush.task.task30.task3003; + +import java.util.concurrent.TransferQueue; + +/** + * Created by ArchMage on 02.05.17. + */ +public class Producer implements Runnable { + private TransferQueue queue; + + public Producer(TransferQueue queue) { + this.queue = queue; + } + + @Override + public void run() { + + try { + for (int i = 1; i <= 9; i++ ) { + System.out.format("Элемент 'ShareItem-%d' добавлен\r\n", i); + queue.offer(new ShareItem("ShareItem-" + i, i)); + + Thread.sleep(100); + + if (queue.hasWaitingConsumer()) { + System.out.format("Consumer в ожидании!\r\n"); + } + } + } catch (InterruptedException e) { + return; + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3003/ShareItem.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3003/ShareItem.java new file mode 100644 index 0000000..b57f012 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3003/ShareItem.java @@ -0,0 +1,59 @@ +package com.javarush.task.task30.task3003; + +//This class shows how to call other constructors using 'this' +public class ShareItem { + public String description; + public int itemId; + + public ShareItem() { + this("Test Item", 0); + } + + public ShareItem(String description) { + this(description, 0); + } + + public ShareItem(int itemId) { + this("Test Item", itemId); + } + + public ShareItem(String description, int itemId) { + this.description = description; + this.itemId = itemId; + } + + public String getDescription() { + return description; + } + + public int getItemId() { + return itemId; + } + + @Override + public String toString() { + return "ShareItem{" + + "description='" + description + '\'' + + ", itemId=" + itemId + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ShareItem shareItem = (ShareItem) o; + + if (itemId != shareItem.itemId) return false; + return description != null ? description.equals(shareItem.description) : shareItem.description == null; + + } + + @Override + public int hashCode() { + int result = description != null ? description.hashCode() : 0; + result = 31 * result + itemId; + return result; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3003/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3003/Solution.java new file mode 100644 index 0000000..c529130 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3003/Solution.java @@ -0,0 +1,31 @@ +package com.javarush.task.task30.task3003; + +import java.util.concurrent.LinkedTransferQueue; +import java.util.concurrent.TransferQueue; + +/* +Экономим время +*/ +public class Solution { + /* + 1. Создай класс Producer. Для этого на красном имени класса нажми Alt+Enter -> Create Class ... + 2. Стань на имени аргумента в конструкторе (queue) и нажми Alt+Enter -> Create Field for Parameter 'queue' -> Enter -> Enter. Имя поля - queue. + 3. Стань на подчеркнутой строке - описании класса. Далее Alt+Enter -> Implement Methods -> Enter. + 4. Проделай п.1-3 для класса Consumer. + */ + + public static void main(String[] args) throws InterruptedException { + TransferQueue queue = new LinkedTransferQueue<>(); + + Thread producer = new Thread(new Producer(queue)); + Thread consumer = new Thread(new Consumer(queue)); + producer.start(); + consumer.start(); + + Thread.sleep(1500); + + producer.interrupt(); + consumer.interrupt(); + } + +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3003/output.txt b/3.JavaMultithreading/src/com/javarush/task/task30/task3003/output.txt new file mode 100644 index 0000000..4f11512 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3003/output.txt @@ -0,0 +1,23 @@ +Элемент 'ShareItem-1' добавлен +Элемент 'ShareItem-2' добавлен +Элемент 'ShareItem-3' добавлен +Элемент 'ShareItem-4' добавлен +Элемент 'ShareItem-5' добавлен +Processing ShareItem{description='ShareItem-1', itemId=1} +Processing ShareItem{description='ShareItem-2', itemId=2} +Processing ShareItem{description='ShareItem-3', itemId=3} +Processing ShareItem{description='ShareItem-4', itemId=4} +Processing ShareItem{description='ShareItem-5', itemId=5} +Consumer в ожидании! +Элемент 'ShareItem-6' добавлен +Processing ShareItem{description='ShareItem-6', itemId=6} +Consumer в ожидании! +Элемент 'ShareItem-7' добавлен +Processing ShareItem{description='ShareItem-7', itemId=7} +Consumer в ожидании! +Элемент 'ShareItem-8' добавлен +Processing ShareItem{description='ShareItem-8', itemId=8} +Consumer в ожидании! +Элемент 'ShareItem-9' добавлен +Processing ShareItem{description='ShareItem-9', itemId=9} +Consumer в ожидании! \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task30/task3003/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task30/task3003/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..6cbafc1 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task30/task3003/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,36 @@ +taskKey="com.javarush.task.task30.task3003" + +Экономим время + +1. Создай Producer и Consumer (См. комментарий к методу main). +2. Создай методы toString, equals и hashCode в классе ShareItem. Для этого в IntelliJ IDEA в теле класса ShareItem выполни: +2.1. Alt+Enter -> toString() -> Enter. +2.2. Alt+Enter -> equals() and hashCode() -> click all 'Next'-s. +2.3. Реализацию методов toString(), equals() и hashCode() оставь такими, какими их сгенерировала IntelliJ IDEA. +3. В Producer и Consumer реализуй метод run так, чтобы вызов метода interrupt прерывал работу consumer и producer трэдов. + +4. Реализация метода run для Producer: +4.1. Используя метод offer добавь в очередь 9 ShareItem-ов с такими параметрами: ("ShareItem-N", N), где N - номер элемента от 1 до 9. +4.2. Перед каждым добавлением выведи фразу "Элемент 'ShareItem-N' добавлен". Используй System.out.format. +4.3. Усыпи трэд на 0.1 секунды. +4.4. Если у очереди есть Consumer, не занятый работой, то выведи фразу "Consumer в ожидании!". +Просмотри методы интерфейса TransferQueue, там есть нужный метод. + +5. Реализация метода run для Consumer: +5.1. Усыпи трэд на 0.45 секунды. +5.2. В бесконечном цикле забери элемент из очереди методом take и выведи в консоль "Processing item.toString()". + +6. Сверь вывод с файлом output.txt. +7. Стек-трейс не выводи в консоль. +8. Для вывода любой информации на экран используй System.out.format. + + +Требования: +1. Создай класс Producer. +2. Создай класс Consumer. +3. В классе ShareItem должны быть созданы методы: toString(), equals(Object) и hashCode(). +4. Метод run() класса Producer должен быть реализован согласно условию задачи. +5. Метод run() класса Consumer должен быть реализован согласно условию задачи. +6. Вывод должен совпадать с файлом output.txt. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3004/BinaryRepresentationTask.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3004/BinaryRepresentationTask.java new file mode 100644 index 0000000..44049b1 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3004/BinaryRepresentationTask.java @@ -0,0 +1,27 @@ +package com.javarush.task.task30.task3004; + +import java.util.concurrent.RecursiveTask; + +/** + * Created by ArchMage on 02.05.17. + */ +public class BinaryRepresentationTask extends RecursiveTask { + private int i; + + public BinaryRepresentationTask(int i) { + this.i = i; + } + + @Override + protected String compute() { + int a = i % 2; + int b = i / 2; + String result = String.valueOf(a); + if (b > 0) { + BinaryRepresentationTask task = new BinaryRepresentationTask(b); + task.fork(); + return task.join() + result; + } + return result; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3004/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3004/Solution.java new file mode 100644 index 0000000..89aac39 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3004/Solution.java @@ -0,0 +1,31 @@ +package com.javarush.task.task30.task3004; + +import java.util.concurrent.ForkJoinPool; + +/* +Fork/Join +*/ +public class Solution { + private String binaryRepresentationMethod(int x) { + int a = x % 2; + int b = x / 2; + String result = String.valueOf(a); + if (b > 0) { + return binaryRepresentationMethod(b) + result; + } + return result; + } + + + public static void main(String[] args) { + Solution solution = new Solution(); + String result1 = solution.binaryRepresentationMethod(6); + System.out.println(result1); + + System.out.println(); + ForkJoinPool forkJoinPool = new ForkJoinPool(); + String result2 = forkJoinPool.invoke(new BinaryRepresentationTask(6)); + System.out.println(result2); + } + +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task30/task3004/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task30/task3004/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..e179689 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task30/task3004/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,18 @@ +taskKey="com.javarush.task.task30.task3004" + +Fork/Join + +1. Создай класс BinaryRepresentationTask. Для этого в IntelliJ IDEA на красном имени класса нажми Alt+Enter -> Create Class ... +(класс должен наследоваться от RecursiveTask). Параметр конструктора - int x. +2. Реализуй логику метода compute - число должно переводиться в двоичное представление. +3. Используй методы fork и join. +4. Пример функциональной реализации - метод binaryRepresentationMethod. + + +Требования: +1. Создай класс BinaryRepresentationTask. +2. В классе BinaryRepresentationTask должен быть переопределен метод compute(). +3. В классе BinaryRepresentationTask в методе compute() используй методы fork() и join(). +4. Метод compute() должен правильно переводить число в двоичную систему счисления. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3005/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3005/Solution.java new file mode 100644 index 0000000..ae2982a --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3005/Solution.java @@ -0,0 +1,60 @@ +package com.javarush.task.task30.task3005; + +import java.util.ArrayList; +import java.util.List; + +/* +Такие хитрые исключения! +*/ +public class Solution { + public static void main(String[] args) { + checkAFlag(new D()); + } + + public static void checkAFlag(D d) { + if ( + d != null + && d.cs != null + && d.cs.size() > 0 + && d.cs.get(0).bs != null + && d.cs.get(0).bs.size() > 0 + && d.cs.get(0).bs.get(0).as != null + && d.cs.get(0).bs.get(0).as.size() > 0 + && d.cs.get(0).bs.get(0).as.get(0) != null + && d.cs.get(0).bs.get(0).as.get(0).flag ) + + { + System.out.println("A's flag is true"); + } else { //all other cases + System.out.println("Oops!"); + } + } + + static class A { + boolean flag = true; + } + + static class B { + List as = new ArrayList<>(); + + { + as.add(new A()); + } + } + + static class C { + List bs = new ArrayList<>(); + + { + bs.add(new B()); + } + } + + static class D { + List cs = new ArrayList<>(); + + { + cs.add(new C()); + } + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task30/task3005/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task30/task3005/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..9ea4b0b --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task30/task3005/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,20 @@ +taskKey="com.javarush.task.task30.task3005" + +Такие хитрые исключения! + +Исправь реализацию метода checkAFlag, чтобы во всех случаях он не приводил к бросанию исключений. +Сохрани логику вывода данных. +Метод main не участвует в тестировании. + + +Требования: +1. В методе checkAFlag должна быть проверка, что d, пришедший в качестве параметра не null. Иначе вывод "Oops!". +2. В методе checkAFlag должна быть проверка, что d.cs не null. Иначе вывод "Oops!". +3. В методе checkAFlag должна быть проверка, что d.cs содержит хотя бы один элемент. Иначе вывод "Oops!". +4. В методе checkAFlag должна быть проверка, что d.cs.get(0).bs не null. Иначе вывод "Oops!". +5. В методе checkAFlag должна быть проверка, что d.cs.get(0).bs содержит хотя бы один элемент. Иначе вывод "Oops!". +6. В методе checkAFlag должна быть проверка, что d.cs.get(0).bs.get(0).as не null. Иначе вывод "Oops!". +7. В методе checkAFlag должна быть проверка, что d.cs.get(0).bs.get(0).as содержит хотя бы один элемент. Иначе вывод "Oops!". +8. В методе checkAFlag должна быть проверка, что d.cs.get(0).bs.get(0).as.get(0).flag равен true. Иначе вывод "Oops!". + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3006/Pair.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3006/Pair.java new file mode 100644 index 0000000..3d0173b --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3006/Pair.java @@ -0,0 +1,22 @@ +package com.javarush.task.task30.task3006; + +public class Pair { + private int x; + private int y; + + public Pair(int x, int y) { + this.x = x; + this.y = y; + } + + @Override + public String toString() { + return String.format("x=%d, y=%d", x, y); + } + + public void swap() { + y = x ^ y; + x = x ^ y; + y = x ^ y; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3006/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3006/Solution.java new file mode 100644 index 0000000..e6ecbe6 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3006/Solution.java @@ -0,0 +1,18 @@ +package com.javarush.task.task30.task3006; + +/* +Swap по-новому +*/ +public class Solution { + public static void main(String[] args) { + /* expected output + x=4, y=5 + x=5, y=4 + */ + + Pair pair = new Pair(4, 5); + System.out.println(pair); + pair.swap(); + System.out.println(pair); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task30/task3006/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task30/task3006/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..9e290c5 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task30/task3006/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,19 @@ +taskKey="com.javarush.task.task30.task3006" + +Swap по-новому + +В классе Pair реализуй метод swap, который должен для x, y менять местами их значения. +Можно использовать только операции: +1) Исключающее или. +2) Присваивание. +3) Исключающее или с присваиванием. +Не оставляй комментарии, не меняй остальной код. + + +Требования: +1. В классе Pair должен присутствовать метод swap(). +2. В классе Pair в методе swap() используй только разрешенные операции. +3. Вызов метода swap() должен поменять значения полей x и y. +4. Не изменяй никакой код, кроме метода swap(). + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3007/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3007/Solution.java new file mode 100644 index 0000000..d9d0752 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3007/Solution.java @@ -0,0 +1,22 @@ +package com.javarush.task.task30.task3007; + +/* +Найдем число 2 в максимальной степени +*/ +public class Solution { + public static void main(String[] args) { + System.out.println(maxPowerOf2(140_000)); //131072 + System.out.println(maxPowerOf2(1026)); //1024 + System.out.println(maxPowerOf2(17)); //16 + } + + public static int maxPowerOf2(int x) { + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + x = x & (~(x>>1)); + return x; + } +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task30/task3007/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task30/task3007/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..3acc942 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task30/task3007/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,25 @@ +taskKey="com.javarush.task.task30.task3007" + +Найдем число 2 в максимальной степени + +Реализуй логику метода maxPowerOf2, который должен возвращать число 2 в максимальной степени, которое получается поместить в переданное число. +Аргументом maxPowerOf2 может быть только положительное целое число. +Используй только операции: +1) Побитовые сдвиги. +2) Побитовое OR. +3) Побитовое AND. +4) Побитовый унарный оператор NOT. +5) Присваивание (можно совмещать разрешенные операции с присваивание, например, &=). +6) Круглые скобки. +Не оставляй комментарии. +Не объявляй никаких переменных, используй только x, который приходит как аргумент метода maxPowerOf2. +Метод main не принимает участия в тестировании. + + +Требования: +1. В классе Solution должен присутствовать метод maxPowerOf2(int). +2. В классе Solution в методе maxPowerOf2(int) используй только разрешенные операции. +3. В классе Solution в методе maxPowerOf2(int) используй только разрешенные операции. +4. Метод maxPowerOf2(int) должен возвращать число 2 в максимальной степени, которое получается поместить в переданное число. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3008/Connection.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/Connection.java new file mode 100644 index 0000000..3aa1de7 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/Connection.java @@ -0,0 +1,46 @@ +package com.javarush.task.task30.task3008; + +import java.io.Closeable; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.net.Socket; +import java.net.SocketAddress; + +/** + * Created by ArchMage on 24.03.17. + */ +public class Connection implements Closeable{ + private final Socket socket; + private final ObjectOutputStream out; + private final ObjectInputStream in; + + public Connection(Socket socket) throws IOException { + this.socket = socket; + out = new ObjectOutputStream(socket.getOutputStream()); + in = new ObjectInputStream(socket.getInputStream()); + } + + public void send(Message message) throws IOException{ + synchronized (out) { + out.writeObject(message); + } + } + + public Message receive() throws IOException, ClassNotFoundException{ + synchronized (in){ + return (Message) in.readObject(); + } + } + + public SocketAddress getRemoteSocketAddress(){ + return socket.getRemoteSocketAddress(); + } + + @Override + public void close() throws IOException { + socket.close(); + in.close(); + out.close(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3008/ConsoleHelper.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/ConsoleHelper.java new file mode 100644 index 0000000..759faeb --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/ConsoleHelper.java @@ -0,0 +1,42 @@ +package com.javarush.task.task30.task3008; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +/** + * Created by ArchMage on 24.03.17. + */ +public class ConsoleHelper { + private static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + + public static void writeMessage(String message){ + System.out.println(message); + } + + public static String readString(){ + String line = null; + while (true) { + try { + line = reader.readLine(); + break; + } catch (IOException e) { + writeMessage("Произошла ошибка при попытке ввода текста. Попробуйте еще раз."); + } + } + + return line; + } + + public static int readInt(){ + int number = 0; + try { + number = Integer.parseInt(readString()); + } catch (NumberFormatException e) { + writeMessage("Произошла ошибка при попытке ввода текста. Попробуйте еще раз."); + number = Integer.parseInt(readString()); + } + + return number; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3008/Message.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/Message.java new file mode 100644 index 0000000..dbdc0eb --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/Message.java @@ -0,0 +1,31 @@ +package com.javarush.task.task30.task3008; + +import java.io.Serializable; + +/** + * Created by ArchMage on 24.03.17. + */ +public class Message implements Serializable { + private final MessageType type; + private final String data; + + public MessageType getType() { + return type; + } + + public String getData() { + return data; + } + + public Message(MessageType type, String data) { + this.type = type; + this.data = data; + } + + public Message(MessageType type) { + this.type = type; + this.data = null; + } + + +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3008/MessageType.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/MessageType.java new file mode 100644 index 0000000..505c792 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/MessageType.java @@ -0,0 +1,13 @@ +package com.javarush.task.task30.task3008; + +/** + * Created by ArchMage on 24.03.17. + */ +public enum MessageType { + NAME_REQUEST, + USER_NAME, + NAME_ACCEPTED, + TEXT, + USER_ADDED, + USER_REMOVED +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3008/Server.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/Server.java new file mode 100644 index 0000000..54db1e1 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/Server.java @@ -0,0 +1,121 @@ +package com.javarush.task.task30.task3008; + + +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + + +/** + * Created by ArchMage on 24.03.17. + */ +public class Server { + private static Map connectionMap = new ConcurrentHashMap<>(); + + private static class Handler extends Thread { + Socket socket; + + public Handler(Socket socket) { + this.socket = socket; + } + + private String serverHandshake(Connection connection) throws IOException { + String name = null; + boolean isAccepted = false; + while (!isAccepted) { + Message output = new Message(MessageType.NAME_REQUEST); + connection.send(output); + Message input = null; + try { + input = connection.receive(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + if (input.getType().equals(MessageType.USER_NAME)) { + name = input.getData(); + if ((!name.isEmpty()) && (connectionMap.get(name) == null)) { + connectionMap.put(name, connection); + connection.send(new Message(MessageType.NAME_ACCEPTED)); + isAccepted = true; + } + } + } + return name; + } + + private void sendListOfUsers(Connection connection, String userName) throws IOException{ + for (Map.Entry entry: connectionMap.entrySet()){ + String name = entry.getKey(); + if (!userName.equals(name)) { + connection.send(new Message(MessageType.USER_ADDED, name)); + } + } + } + + private void serverMainLoop(Connection connection, String userName) throws IOException, ClassNotFoundException { + while (true){ + Message message = connection.receive(); + if (MessageType.TEXT.equals(message.getType())) { + sendBroadcastMessage(new Message(MessageType.TEXT, userName + ": " + message.getData())); + } else { ConsoleHelper.writeMessage("Not a message"); } + } + } + + public void run(){ + String userName = null; + if (socket != null && socket.getRemoteSocketAddress() != null) { + ConsoleHelper.writeMessage("Established a new connection to a remote socket address: " + socket.getRemoteSocketAddress()); + } + + //ConsoleHelper.writeMessage("Remote connection with address" + socket.getRemoteSocketAddress() + " established!"); + try (Connection connection = new Connection(socket);) + { + ConsoleHelper.writeMessage("Connection with port " + connection.getRemoteSocketAddress()); + userName = serverHandshake(connection); + sendBroadcastMessage(new Message(MessageType.USER_ADDED, userName)); + sendListOfUsers(connection, userName); + serverMainLoop(connection, userName); + } catch (IOException e) { + ConsoleHelper.writeMessage(e.getMessage()); + } catch (ClassNotFoundException e) { + ConsoleHelper.writeMessage(e.getMessage()); + } finally { + if ( userName != null) { + connectionMap.remove(userName); + sendBroadcastMessage(new Message(MessageType.USER_REMOVED, userName)); + ConsoleHelper.writeMessage("Remote connection closed successfully"); + } + } + } + + } + + public static void sendBroadcastMessage(Message message){ + for (Map.Entry entry: connectionMap.entrySet()){ + try { + entry.getValue().send(message); + } catch (IOException e) { + ConsoleHelper.writeMessage("Cannot send a message"); + } + } + } + + public static void main(String[] args){ + //int port = ConsoleHelper.readInt(); + try( + ServerSocket serverSocket = new ServerSocket(ConsoleHelper.readInt()); + ) + { + ConsoleHelper.writeMessage("Server started!"); + while (true) { + Socket incomeSocket = serverSocket.accept(); + new Handler(incomeSocket).start(); + } + + } catch (IOException e){ + ConsoleHelper.writeMessage(e.getMessage()); + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/BotClient.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/BotClient.java new file mode 100644 index 0000000..4afe136 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/BotClient.java @@ -0,0 +1,84 @@ +package com.javarush.task.task30.task3008.client; + +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; + +/** + * Created by ArchMage on 27.03.17. + */ +public class BotClient extends Client{ + public class BotSocketThread extends SocketThread{ + @Override + protected void clientMainLoop() throws IOException, ClassNotFoundException { + sendTextMessage("Привет чатику. Я бот. Понимаю команды: дата, день, месяц, год, время, час, минуты, секунды."); + super.clientMainLoop(); + } + + @Override + protected void processIncomingMessage(String message) { + super.processIncomingMessage(message); + String command = null; + String name = null; + SimpleDateFormat format = null; + if (message != null && message.contains(":")) { + int index = message.indexOf(": "); + if (index >= 0){ + name = message.substring(0, index ); + command = message.substring(index + 2); + switch (command) { + case "дата": + format = new SimpleDateFormat("d.MM.YYYY"); + break; + case "день": + format = new SimpleDateFormat("d"); + break; + case "месяц": + format = new SimpleDateFormat("MM"); + break; + case "год": + format = new SimpleDateFormat("YYYY"); + break; + case "время": + format = new SimpleDateFormat("H:mm:ss"); + break; + case "час": + format = new SimpleDateFormat("H"); + break; + case "минуты": + format = new SimpleDateFormat("m"); + break; + case "секунды": + format = new SimpleDateFormat("s"); + break; + } + Date currentDate = Calendar.getInstance().getTime(); + if (format != null && name != null) { + sendTextMessage(String.format("Информация для %s: %s", name, format.format(currentDate))); + } + } + } + } + } + + @Override + protected SocketThread getSocketThread() { + return new BotSocketThread(); + } + + @Override + protected boolean shouldSendTextFromConsole() { + return false; + } + + @Override + protected String getUserName() { + return "date_bot_" + (int) (Math.random() * 100); + } + + public static void main(String[] args){ + BotClient botClient = new BotClient(); + botClient.run(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/Client.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/Client.java new file mode 100644 index 0000000..d15677f --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/Client.java @@ -0,0 +1,148 @@ +package com.javarush.task.task30.task3008.client; + +import com.javarush.task.task30.task3008.Connection; +import com.javarush.task.task30.task3008.ConsoleHelper; +import com.javarush.task.task30.task3008.Message; +import com.javarush.task.task30.task3008.MessageType; + +import java.io.IOException; +import java.net.Socket; + +/** + * Created by ArchMage on 27.03.17. + */ +public class Client{ + protected Connection connection; + private volatile boolean clientConnected = false; + + public class SocketThread extends Thread{ + protected void processIncomingMessage(String message){ + ConsoleHelper.writeMessage(message); + } + + protected void informAboutAddingNewUser(String userName){ + ConsoleHelper.writeMessage("User " + userName + " is connected"); + } + + protected void informAboutDeletingNewUser(String userName){ + ConsoleHelper.writeMessage("User " + userName + " has left the conversation"); + } + + protected void notifyConnectionStatusChanged(boolean clientConnected){ + Client.this.clientConnected = clientConnected; + synchronized (Client.this){ + Client.this.notifyAll(); + } + } + + protected void clientHandshake() throws IOException, ClassNotFoundException{ + while (true){ + Message message = connection.receive(); + if (MessageType.NAME_REQUEST.equals(message.getType())) { + connection.send(new Message(MessageType.USER_NAME, getUserName())); + } else if (MessageType.NAME_ACCEPTED.equals(message.getType())) { + notifyConnectionStatusChanged(true); + break; + } else { + throw new IOException("Unexpected MessageType"); + } + + } + } + + protected void clientMainLoop() throws IOException, ClassNotFoundException { + while (true){ + Message message = connection.receive(); + if (MessageType.TEXT.equals(message.getType())) { + processIncomingMessage(message.getData()); + } else if (MessageType.USER_ADDED.equals(message.getType())) { + informAboutAddingNewUser(message.getData()); + } else if (MessageType.USER_REMOVED.equals(message.getType())) { + informAboutDeletingNewUser(message.getData()); + } else { + throw new IOException("Unexpected MessageType"); + } + + } + } + + public void run(){ + String ipAddress = getServerAddress(); + int port = getServerPort(); + try { + Socket socket = new Socket(ipAddress, port); + connection = new Connection(socket); + clientHandshake(); + clientMainLoop(); + } catch (IOException | ClassNotFoundException e) { + notifyConnectionStatusChanged(false); + } + } + } + + protected String getServerAddress(){ + System.out.println("Enter server ip address"); + return ConsoleHelper.readString(); + } + + protected int getServerPort(){ + System.out.println("Enter server port number"); + return ConsoleHelper.readInt(); + } + + protected String getUserName(){ + System.out.println("Enter your name"); + return ConsoleHelper.readString(); + } + + protected boolean shouldSendTextFromConsole(){ + return true; + } + + protected SocketThread getSocketThread(){ + return new SocketThread(); + } + + protected void sendTextMessage(String text){ + try { + connection.send(new Message(MessageType.TEXT ,text)); + } catch (IOException e) { + clientConnected = false; + ConsoleHelper.writeMessage(e.getMessage()); + } + } + + public void run(){ + SocketThread socketThread = getSocketThread(); + socketThread.setDaemon(true); + socketThread.start(); + synchronized (this){ + try { + wait(); + if (clientConnected) { + ConsoleHelper.writeMessage("Соединение установлено. Для выхода наберите команду ‘exit’."); + String message = null; + while (clientConnected){ + message = ConsoleHelper.readString(); + if ("exit".equals(message)) { break; } + if (shouldSendTextFromConsole()) { + sendTextMessage(message); + } + } + + } else { + ConsoleHelper.writeMessage("Произошла ошибка во время работы клиента."); + } + } catch (InterruptedException e) { + ConsoleHelper.writeMessage(e.getMessage()); + return; + } + } + } + + + public static void main(String[] args){ + Client client = new Client(); + client.run(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/ClientGuiController.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/ClientGuiController.java new file mode 100644 index 0000000..32d151d --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/ClientGuiController.java @@ -0,0 +1,74 @@ +package com.javarush.task.task30.task3008.client; + +/** + * Created by ArchMage on 27.03.17. + */ +public class ClientGuiController extends Client { + private ClientGuiModel model = new ClientGuiModel(); + private ClientGuiView view = new ClientGuiView(this); + + public ClientGuiController() { + + } + + public ClientGuiModel getModel(){ + return model; + } + + public class GuiSocketThread extends SocketThread{ + @Override + protected void processIncomingMessage(String message) { + model.setNewMessage(message); + view.refreshMessages(); + } + + @Override + protected void informAboutAddingNewUser(String userName) { + model.addUser(userName); + view.refreshUsers(); + } + + @Override + protected void informAboutDeletingNewUser(String userName) { + model.deleteUser(userName); + view.refreshUsers(); + } + + @Override + protected void notifyConnectionStatusChanged(boolean clientConnected) { + view.notifyConnectionStatusChanged(clientConnected); + } + + } + + @Override + protected SocketThread getSocketThread() { + return new GuiSocketThread(); + } + + @Override + public void run() { + SocketThread socketThread = getSocketThread(); + socketThread.run(); + } + + @Override + protected String getServerAddress() { + return view.getServerAddress(); + } + + @Override + protected int getServerPort() { + return view.getServerPort(); + } + + @Override + protected String getUserName() { + return view.getUserName(); + } + + public static void main(String[] args){ + ClientGuiController controller = new ClientGuiController(); + controller.run(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/ClientGuiModel.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/ClientGuiModel.java new file mode 100644 index 0000000..f9a61f0 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/ClientGuiModel.java @@ -0,0 +1,33 @@ +package com.javarush.task.task30.task3008.client; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +/** + * Created by ArchMage on 27.03.17. + */ +public class ClientGuiModel { + private final Set allUserNames = new HashSet(); + private String newMessage; + + public Set getAllUserNames() { + return Collections.unmodifiableSet(allUserNames); + } + + public String getNewMessage() { + return newMessage; + } + + public void setNewMessage(String newMessage) { + this.newMessage = newMessage; + } + + public void addUser(String newUserName){ + allUserNames.add(newUserName); + } + + public void deleteUser(String userName){ + allUserNames.remove(userName); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/ClientGuiView.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/ClientGuiView.java new file mode 100644 index 0000000..aee2ccd --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/client/ClientGuiView.java @@ -0,0 +1,106 @@ +package com.javarush.task.task30.task3008.client; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class ClientGuiView { + private final ClientGuiController controller; + + private JFrame frame = new JFrame("Чат"); + private JTextField textField = new JTextField(50); + private JTextArea messages = new JTextArea(10, 50); + private JTextArea users = new JTextArea(10, 10); + + public ClientGuiView(ClientGuiController controller) { + this.controller = controller; + initView(); + } + + private void initView() { + textField.setEditable(false); + messages.setEditable(false); + users.setEditable(false); + + frame.getContentPane().add(textField, BorderLayout.NORTH); + frame.getContentPane().add(new JScrollPane(messages), BorderLayout.WEST); + frame.getContentPane().add(new JScrollPane(users), BorderLayout.EAST); + frame.pack(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + + textField.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + controller.sendTextMessage(textField.getText()); + textField.setText(""); + } + }); + } + + public String getServerAddress() { + return JOptionPane.showInputDialog( + frame, + "Введите адрес сервера:", + "Конфигурация клиента", + JOptionPane.QUESTION_MESSAGE); + } + + public int getServerPort() { + while (true) { + String port = JOptionPane.showInputDialog( + frame, + "Введите порт сервера:", + "Конфигурация клиента", + JOptionPane.QUESTION_MESSAGE); + try { + return Integer.parseInt(port.trim()); + } catch (Exception e) { + JOptionPane.showMessageDialog( + frame, + "Был введен некорректный порт сервера. Попробуйте еще раз.", + "Конфигурация клиента", + JOptionPane.ERROR_MESSAGE); + } + } + } + + public String getUserName() { + return JOptionPane.showInputDialog( + frame, + "Введите ваше имя:", + "Конфигурация клиента", + JOptionPane.QUESTION_MESSAGE); + } + + public void notifyConnectionStatusChanged(boolean clientConnected) { + textField.setEditable(clientConnected); + if (clientConnected) { + JOptionPane.showMessageDialog( + frame, + "Соединение с сервером установлено", + "Чат", + JOptionPane.INFORMATION_MESSAGE); + } else { + JOptionPane.showMessageDialog( + frame, + "Клиент не подключен к серверу", + "Чат", + JOptionPane.ERROR_MESSAGE); + } + + } + + public void refreshMessages() { + messages.append(controller.getModel().getNewMessage() + "\n"); + } + + public void refreshUsers() { + ClientGuiModel model = controller.getModel(); + StringBuilder sb = new StringBuilder(); + for (String userName : model.getAllUserNames()) { + sb.append(userName).append("\n"); + } + users.setText(sb.toString()); + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task30/task3008/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..84f3a87 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task30/task3008/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,189 @@ +taskKey="com.javarush.task.task30.task3008.big22" + +Чат (22) + +Итак, подведем итог: +• Ты написал сервер для обмена текстовыми сообщениями. +• Ты написал консольный клиент, который умеет подключаться к серверу и +обмениваться сообщениями с другими участниками. +• Ты написал бот клиента, который может принимать запросы и отправлять данные о +текущей дате и времени. +• Ты написал клиента для чата с графическим интерфейсом. + +Что можно добавить или улучшить: +• Можно добавить поддержку приватных сообщений (когда сообщение отправляется не +всем, а какому-то конкретному участнику). +• Можно расширить возможности бота, попробовать научить его отвечать на +простейшие вопросы или время от времени отправлять шутки. +• Добавить возможность пересылки файлов между пользователями. +• Добавить контекстное меню в графический клиент, например, для отправки +приватного сообщения кому-то из списка участников. +• Добавить раскраску сообщений в графическом клиенте в зависимости от отправителя. +• Добавить блокировку сервером участников за что-либо, например, ненормативную +лексику в сообщениях. +• Добавить еще миллион фич и полезностей! + +Ты научился: +• Работать с сокетами. +• Пользоваться сериализацией и десериализацией. +• Создавать многопоточные приложения, синхронизировать их, применять модификатор +volatile, пользоваться классами из библиотеки java.util.concurrent. +• Применять паттерн MVC. +• Использовать внутренние и вложенные классы. +• Работать с библиотекой Swing. +• Применять классы Calendar и SimpleDateFormat. + +Так держать! + + +Чат (21) + +У меня есть отличнейшая новость для тебя. Компонент представление (View) уже готов. Я +добавил класс ClientGuiView. Он использует библиотеку javax.swing. Ты должен как следует +разобраться в каждой строчке этого класса. Если тебе все понятно – это замечательно, если +нет – обязательно найди ответы на свои вопросы с помощью дебага, документации или +поиска в Интернет. + +Осталось написать компонент контроллер (Controller): +1) Создай класс ClientGuiController унаследованный от Client. +2) Создай и инициализируй поле, отвечающее за модель ClientGuiModel +model. +3) Создай и инициализируй поле, отвечающее за представление ClientGuiView +view. Подумай, что нужно передать в конструктор при инициализации объекта. +4) Добавь внутренний класс GuiSocketThread унаследованный от SocketThread. +Класс GuiSocketThread должен быть публичным. В нем переопредели следующие +методы: +а) void processIncomingMessage(String message) – должен устанавливать новое +сообщение у модели и вызывать обновление вывода сообщений у +представления. +б) void informAboutAddingNewUser(String userName) – должен добавлять нового +пользователя в модель и вызывать обновление вывода пользователей у +отображения. +в) void informAboutDeletingNewUser(String userName) – должен удалять +пользователя из модели и вызывать обновление вывода пользователей у +отображения. +г) void notifyConnectionStatusChanged(boolean clientConnected) – должен вызывать +аналогичный метод у представления. +5) Переопредели методы в классе ClientGuiController: +а) SocketThread getSocketThread() – должен создавать и возвращать объект типа +GuiSocketThread. +б) void run() – должен получать объект SocketThread через метод getSocketThread() +и вызывать у него метод run(). Разберись, почему нет необходимости вызывать +метод run в отдельном потоке, как мы это делали для консольного клиента. +в) getServerAddress(), getServerPort(),getUserName(). Они должны вызывать +одноименные методы из представления (view). +6) Реализуй метод ClientGuiModel getModel(), который должен возвращать модель. +7) Реализуй метод main(), который должен создавать новый объект +ClientGuiController и вызывать у него метод run(). +Запусти клиента с графическим окном, нескольких консольных клиентов и убедись, что +все работает корректно. + + + +Чат (20) + +Консольный клиент мы уже реализовали, чат бота тоже сделали, почему бы не сделать +клиента с графическим интерфейсом? Он будет так же работать с нашим сервером, но +иметь графическое окно, кнопки и т.д. +Итак, приступим. При написании графического клиента будет очень уместно воспользоваться +паттерном MVC (Model-View-Controller). Ты уже должен был с ним сталкиваться, если необходимо, +освежи свои знания про MVC с помощью Интернет. В нашей задаче самая простая реализация +будет у класса, отвечающего за модель (Model). + +Давай напишем его: +1) Создай класс ClientGuiModel в пакете client. Все классы клиента должны быть созданы в этом +пакете. +2) Добавь в него множество(set) строк в качестве final поля allUserNames. +В нем будет храниться список всех участников чата. Проинициализируй его. +3) Добавь поле String newMessage, в котором будет храниться новое сообщение, +которое получил клиент. +4) Добавь геттер для allUserNames, запретив модифицировать возвращенное +множество. Разберись, как это можно сделать с помощью метода класса Collections. +5) Добавь сеттер и геттер для поля newMessage. +6) Добавь метод void addUser(String newUserName), который должен добавлять +имя участника во множество, хранящее всех участников. +7) Добавь метод void deleteUser(String userName), который будет удалять имя +участника из множества. + + + +Чат (19) + +Сейчас будем реализовывать класс BotSocketThread, вернее переопределять некоторые +его методы, весь основной функционал он уже унаследовал от SocketThread. + +1) Переопредели метод clientMainLoop(): +а) С помощью метода sendTextMessage() отправь сообщение с текстом +"Привет чатику. Я бот. Понимаю команды: дата, день, месяц, год, время, час, минуты, секунды." +б) Вызови реализацию clientMainLoop() родительского класса. +2) Переопредели метод processIncomingMessage(String message). Он должен +следующим образом обрабатывать входящие сообщения: +а) Вывести в консоль текст полученного сообщения message. +б) Получить из message имя отправителя и текст сообщения. Они разделены ": ". +в) Отправить ответ в зависимости от текста принятого сообщения. Если текст +сообщения: +"дата" – отправить сообщение содержащее текущую дату в формате "d.MM.YYYY"; +"день" – в формате"d"; +"месяц" - "MMMM"; +"год" - "YYYY"; +"время" - "H:mm:ss"; +"час" - "H"; +"минуты" - "m"; +"секунды" - "s". +Указанный выше формат используй для создания объекта SimpleDateFormat. Для +получения текущей даты необходимо использовать класс Calendar и метод +getTime(). +Ответ должен содержать имя клиента, который прислал запрос и ожидает ответ, +например, если Боб отправил запрос "время", мы должны отправить ответ +"Информация для Боб: 12:30:47". +Наш бот готов. Запусти сервер, запусти бота, обычного клиента и убедись, что все работает правильно. +Помни, что message бывают разных типов и не всегда содержат ":" + + + +Чат (18) + +Иногда бывают моменты, что не находится достойного собеседника. Не общаться же с +самим собой :). Давай напишем бота, который будет представлять собой клиента, который +автоматически будет отвечать на некоторые команды. Проще всего реализовать бота, +который сможет отправлять текущее время или дату, когда его кто-то об этом попросит. + +С него и начнем: +1) Создай новый класс BotClient в пакете client. Он должен быть унаследован от +Client. +2) В классе BotClient создай внутренний класс BotSocketThread унаследованный от +SocketThread. Класс BotSocketThread должен быть публичным. +3) Переопредели методы: +а) getSocketThread(). Он должен создавать и возвращать объект класса +BotSocketThread. +б) shouldSendTextFromConsole(). Он должен всегда возвращать false. Мы не хотим, +чтобы бот отправлял текст введенный в консоль. +в) getUserName(), метод должен генерировать новое имя бота, например: +date_bot_XX, где XX – любое число от 0 до 99. Для генерации XX используй метод Math.random(). +4) Добавь метод main. Он должен создавать новый объект BotClient и вызывать у +него метод run(). + + + +Чат (17) + +Последний, но самый главный метод класса SocketThread – это метод void run(). Добавь +его. Его реализация с учетом уже созданных методов выглядит очень просто. + +Давай напишем ее: +1) Запроси адрес и порт сервера с помощью методов getServerAddress() и +getServerPort(). +2) Создай новый объект класса java.net.Socket, используя данные, полученные в +предыдущем пункте. +3) Создай объект класса Connection, используя сокет из п.17.2. +4) Вызови метод, реализующий "рукопожатие" клиента с сервером +(clientHandshake()). +5) Вызови метод, реализующий основной цикл обработки сообщений сервера. +6) При возникновении исключений IOException или ClassNotFoundException +сообщи главному потоку о проблеме, используя notifyConnectionStatusChanged и false +в качестве параметра. + +Клиент готов, можешь запустить сервер, несколько клиентов и проверить как все работает. + + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3009/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3009/Solution.java new file mode 100644 index 0000000..0dccfe0 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3009/Solution.java @@ -0,0 +1,36 @@ +package com.javarush.task.task30.task3009; + +import java.math.BigInteger; +import java.util.HashSet; +import java.util.Set; + +/* +Палиндром? +*/ + +public class Solution { + public static void main(String[] args) { + System.out.println(getRadix("112")); //expected output: [3, 27, 13, 15] + System.out.println(getRadix("123")); //expected output: [6] + System.out.println(getRadix("5321")); //expected output: [] + System.out.println(getRadix("1A")); //expected output: [] + } + + private static Set getRadix(String number){ + Set result = new HashSet<>(); + try { + BigInteger bigInt = new BigInteger(number); + for (int i = 2; i <= 36; i++) { + + String input = bigInt.toString(i); + StringBuilder inputInBuilder = new StringBuilder(input); + StringBuilder compareString = new StringBuilder(input).reverse(); + if (inputInBuilder.toString().equals(compareString.toString())) { result.add(i); } + + } + } catch (NumberFormatException e) { + } + + return result; + } +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task30/task3009/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task30/task3009/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..314e727 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task30/task3009/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,23 @@ +taskKey="com.javarush.task.task30.task3009" + +Палиндром? + +Объяви и реализуй логику приватного статического метода Set getRadix(String number), в +котором нужно определить, в каких системах счисления (от 2 до 36 включительно) представление числа number +(передается в десятичной системе счисления) является палиндромом и добавить индекс таких систем в результат. +Если переданное число некорректно - возвращай пустой HashSet. +В системах счисления с основанием большим 10 в качестве цифр используются латинские буквы. К примеру, числу +35 в десятичной системе соответствует число "Z" в системе с основанием 36. + +Метод main не принимает участие в тестировании. +P.S.: В методе getRadix перехватывай NumberFormatException. Стек-трейс выводить не нужно. + + +Требования: +1. Необходимо объявить приватный статический метод Set getRadix(String number). +2. Метод getRadix в случае некорректных входных данных должен возвращать пустой HashSet. +3. Методе getRadix не должен бросать NumberFormatException. +4. Метод getRadix не должен ничего выводить в консоль. +5. Метод getRadix должен возвращать множество согласно условию задачи. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3010/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3010/Solution.java new file mode 100644 index 0000000..86f500a --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3010/Solution.java @@ -0,0 +1,28 @@ +package com.javarush.task.task30.task3010; + +/* +Минимальное допустимое основание системы счисления +*/ + +import java.math.BigInteger; + +public class Solution { + public static void main(String[] args) { + //напишите тут ваш код + if (args == null || args.length == 0) { return; } + String input = new String(args[0]); + input = input.replaceAll("[0-9a-zA-Z]", ""); + if (input.length() != 0) { System.out.println("incorrect"); } + else { + input = new String(args[0]).toLowerCase(); + for (int i = 2; i <= 36; i++){ + try { + BigInteger bigI = new BigInteger(input, i); + System.out.println(i); + break; + } catch (NumberFormatException e){ + } + } + } + } +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task30/task3010/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task30/task3010/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..1a1839c --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task30/task3010/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,36 @@ +taskKey="com.javarush.task.task30.task3010" + +Минимальное допустимое основание системы счисления + +В метод main первым аргументом приходит строка, которая содержит последовательность символов (Все символы в +строке имеют коды в таблице ASCII от 32 до 127 включительно). Длина строки не превышает 255 символов. Нужно +реализовать программу, которая по входящей строке определит, является ли содержимое строки записью числа в +системе счисления с основанием не больше 36 включительно. Если является - нужно вывести минимальное +основание системы счисления, в которой это число может существовать. Если не является - необходимо вывести +"incorrect". +В системах счисления с основанием большим 10 в качестве цифр используются латинские буквы. К примеру, числу +35 в десятичной системе соответствует число "Z" в системе с основанием 36. Так как рассматриваем +позиционные системы счисления - минимальное основание, которое должна выводить программа, это 2. +Если возникают любые исключения - перехватывай их и не выводи стек-трейс. + +Пример1: +Вход: 00 +Ожидаемый вывод: 2 + +Пример2: +Вход: 12AS08z +Ожидаемый вывод: 36 + +Пример3: +Вход: 12AS08Z/ +Ожидаемый вывод: incorrect + + +Требования: +1. Если возникло любое исключение - необходимо перехватить его и не выводить стек-трейс. +2. Если входящая строка содержит что-либо, кроме латинских букв и цифр - необходимо вывести "incorrect". +3. Если входящая строка корректна - необходимо вывести основание системы счисления. +4. Минимальное основание, которое выводит программа должно равняться 2. +5. Вывод программы должен соответствовать условию. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3011/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3011/Solution.java new file mode 100644 index 0000000..f342766 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3011/Solution.java @@ -0,0 +1,107 @@ +package com.javarush.task.task30.task3011; + +/* +Сделай одно изменение кода +*/ + +public class Solution { + public static void main(String[] args) { + Solution solution = new Solution(); + solution.doSmth(new A(), null, null); + } + + public void doSmth(A a, B b, C c) { + try { + if (a != null && a.getName() != null) { + //do nothing + } + } catch (NullPointerException e) { + a = new A(); + a.setName("A"); + } + try { + if (a != null && a.getName() == null) { + a.setName("A"); + } + } catch (NullPointerException e) { + } + if (a == null) { + a = new A(); + a.setName("A"); + } + try { + if (b != null && b.getName() != null) { + //do nothing + } + } catch (NullPointerException e) { + b = new B(); + b.setName("B"); + } + try { + if (b != null && b.getName() == null) { + b.setName("B"); + } + } catch (NullPointerException e) { + } + if (b == null) { + b = new B(); + b.setName("B"); + } + try { + if (c != null & c.getName() != null) { + } + } catch (NullPointerException e) { + c = new C(); + c.setName("C"); + } + try { + if (c != null && c.getName() == null) { + c.setName("C"); + } + } catch (NullPointerException e) { + } + if (c == null) { + c = new C(); + c.setName("null"); + } + System.out.print(a.getName()); + System.out.print(b.getName()); + System.out.print(c.getName()); + } + + static class A { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + static class B { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + static class C { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task30/task3011/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task30/task3011/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..8eeca71 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task30/task3011/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,18 @@ +taskKey="com.javarush.task.task30.task3011" + +Сделай одно изменение кода + +Внеси одну правку в код программы, чтобы вывод всегда был "ABC", даже если в метод doSmth +передавать параметрами null. +Не изменяй и не добавляй строковые литералы. Не изменяй строки с выводом данных на экран. +Не добавляй сеттеры. + + +Требования: +1. Вывод метода doSmth должен быть "ABC", если в него передать объекты типа A, B и C. +2. Вывод метода doSmth должен быть "ABC", если в него передать null, null, null. +3. Запрещено изменять или добавлять строковые литералы, запрещено добавлять сеттеры. +4. Запрещено изменять строки с выводом данных на экран. +5. Необходимо внести одну правку в код программы. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3012/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3012/Solution.java new file mode 100644 index 0000000..5f13255 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3012/Solution.java @@ -0,0 +1,49 @@ +package com.javarush.task.task30.task3012; + +/* +Получи заданное число +*/ + + +public class Solution { + public static void main(String[] args) { + Solution solution = new Solution(); + solution.createExpression(74); + //System.out.println(Integer.toString(74, 3)); + } + + + public void createExpression(int number) { + int[] array = {1, 3, 9, 27, 81, 243, 729, 2187}; + String resultStr = number + " ="; + for (int i = 0; i < 6560; i++){ + String tryString = String.format("%08d" ,Integer.parseInt(Integer.toString(i, 3))); + int summ = 0; + for (int j = 0; j < 8; j++){ + if ("0".equals(String.valueOf(tryString.charAt(j)))){ + summ += array[j]; + }else if ("1".equals(String.valueOf(tryString.charAt(j)))) { + + }else if ("2".equals(String.valueOf(tryString.charAt(j)))) { + summ -= array[j]; + } + } + if (summ == number) { + for (int j = 0; j < 8; j++){ + if ("0".equals(String.valueOf(tryString.charAt(j)))) { + resultStr = resultStr + " + " + array[j]; + }else if ("1".equals(String.valueOf(tryString.charAt(j)))) { + + }else if ("2".equals(String.valueOf(tryString.charAt(j)))) { + resultStr = resultStr + " - " + array[j]; + } + } + break; + } + } + System.out.println(resultStr); + //напишите тут ваш код + } + + +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task30/task3012/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task30/task3012/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..899d525 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task30/task3012/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,37 @@ +taskKey="com.javarush.task.task30.task3012" + +Получи заданное число + +Реализуй метод createExpression(int number). +Метод createExpression вызывается с одним параметром number. Этот параметр - число от 1 до 3000 включительно. +Нужно вывести арифметическое выражение, результатом которого является число number. +Можно использовать числа: 1, 3, 9, 27, 81, 243, 729, 2187 не более, чем по одному разу. +Можно использовать знаки: "+" и "-" любое количество раз. +Обрати внимание, что перед каждым числом в искомой строке обязательно должен быть знак плюс или минус. +Перед выражением выведи [переданное число] =. (Смотри примеры вывода ниже). + +Пример1: +Переданное число: 74 +Ожидаемый вывод: 74 = - 1 + 3 - 9 + 81 + +Пример2: +Переданное число: 1234 +Ожидаемый вывод: 1234 = + 1 - 9 + 27 - 243 - 729 + 2187 + +При выводе выражения используй числа ТОЛЬКО В ВОЗРАСТАЮЩЕМ порядке! +Переданное число: 2 +Ожидаемый вывод: 2 = - 1 + 3 //правильно +Ожидаемый вывод: 2 = + 3 - 1 //НЕ правильно +Метод main не участвует в тестировании. + +Подсказка: +Почитай в интернете про троичную симметричную систему счисления. + + +Требования: +1. В начале строчки вывода должно быть расположено число, которое передано в метод createExpression в качестве параметра и знак "=". +2. В выражении можно использовать только числа: 1, 3, 9, 27, 81, 243, 729, 2187 не более, чем по одному разу. +3. В выражении можно использовать только знаки "+" и "-" любое количество раз. +4. Метод createExpression должен быть реализован согласно условию. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task30/task3013/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task30/task3013/Solution.java new file mode 100644 index 0000000..f10ad6a --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task30/task3013/Solution.java @@ -0,0 +1,27 @@ +package com.javarush.task.task30.task3013; + +/* +Набираем код +*/ + +public class Solution { + public static void main(String[] args) { + Solution solution = new Solution(); + int number = Integer.MAX_VALUE - 133; + System.out.println(Integer.toString(number, 2)); + + String result = Integer.toString(solution.resetLowerBits(number), 2); + System.out.println(result); + } + + public int resetLowerBits(int number) { + number |= number >> 1; + number |= number >> 2; + number |= number >> 4; + number |= number >> 8; + number |= number >> 16; + number = number & (~number >> 1); + return number; + //напишите тут ваш код + } +} \ No newline at end of file diff --git "a/3.JavaMultithreading/src/com/javarush/task/task30/task3013/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task30/task3013/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..0a7ab12 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task30/task3013/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,47 @@ +taskKey="com.javarush.task.task30.task3013" + +Набираем код + +Необходимо реализовать публичный метод int resetLowerBits(int number), который обнуляет все биты в числе +number, кроме самого старшего равного единице, и возвращает это число. +Число типа int это 4 байта = 32 бита. Если в метод передано число 3456, его представление в виде битов +будет 00000000 00000000 00001101 10000000. В методе нужно обнулить все младшие биты, то есть на выходе +ожидается что число, представленное в виде битов, будет иметь вид: 00000000 00000000 00001000 00000000. +Это число 2048. +Еще несколько примеров: +Пример 1: +на входе: 1 +на выходе: 1 + +Пример 2: +на входе: 4 +на выходе: 4 + +Пример 3: +на входе: 255 +на выходе: 128 + +Параметр метода resetLowerBits может быть от 1 до Integer.MAX_VALUE включительно. +Используй только операции: +1) = +2) | +3) & +4) >> +5) << +6) ~ +7) цифры от 0 до 9 включительно +8) круглые скобки +9) оператор "return" для возврата результата метода. + +ЗАПРЕЩЕНО создавать переменные, использовать циклы, условные операторы и прочее. +Имя параметра метода resetLowerBits не изменяй (должно быть "number"). +Метод main не принимает участия в тестировании. + + +Требования: +1. В классе Solution должен присутствовать публичный метод int resetLowerBits(int). +2. Параметр метода resetLowerBits(int) должен называться number. +3. В классе Solution в методе resetLowerBits(int) используй только разрешенные операции. +4. Метод resetLowerBits должен работать согласно условию задачи. + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/Archiver.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/Archiver.java new file mode 100644 index 0000000..b5fe7c4 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/Archiver.java @@ -0,0 +1,37 @@ +package com.javarush.task.task31.task3110; + +import com.javarush.task.task31.task3110.exception.WrongZipFileException; + +import java.io.IOException; + +public class Archiver { + public static void main(String[] args) throws IOException { + + Operation operation = null; + do { + try { + operation = askOperation(); + CommandExecutor.execute(operation); + } catch (WrongZipFileException e) { + ConsoleHelper.writeMessage("Вы не выбрали файл архива или выбрали неверный файл."); + } catch (Exception e) { + ConsoleHelper.writeMessage("Произошла ошибка. Проверьте введенные данные."); + } + + } while (operation != Operation.EXIT); + } + + + public static Operation askOperation() throws IOException { + ConsoleHelper.writeMessage(""); + ConsoleHelper.writeMessage("Выберите операцию:"); + ConsoleHelper.writeMessage(String.format("\t %d - упаковать файлы в архив", Operation.CREATE.ordinal())); + ConsoleHelper.writeMessage(String.format("\t %d - добавить файл в архив", Operation.ADD.ordinal())); + ConsoleHelper.writeMessage(String.format("\t %d - удалить файл из архива", Operation.REMOVE.ordinal())); + ConsoleHelper.writeMessage(String.format("\t %d - распаковать архив", Operation.EXTRACT.ordinal())); + ConsoleHelper.writeMessage(String.format("\t %d - просмотреть содержимое архива", Operation.CONTENT.ordinal())); + ConsoleHelper.writeMessage(String.format("\t %d - выход", Operation.EXIT.ordinal())); + + return Operation.values()[ConsoleHelper.readInt()]; + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/CommandExecutor.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/CommandExecutor.java new file mode 100644 index 0000000..e3c0c86 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/CommandExecutor.java @@ -0,0 +1,26 @@ +package com.javarush.task.task31.task3110; + +import com.javarush.task.task31.task3110.command.*; + +import java.util.HashMap; +import java.util.Map; + +public class CommandExecutor { + private static final Map allKnownCommandsMap = new HashMap<>(); + + static { + allKnownCommandsMap.put(Operation.CREATE, new ZipCreateCommand()); + allKnownCommandsMap.put(Operation.ADD, new ZipAddCommand()); + allKnownCommandsMap.put(Operation.REMOVE, new ZipRemoveCommand()); + allKnownCommandsMap.put(Operation.EXTRACT, new ZipExtractCommand()); + allKnownCommandsMap.put(Operation.CONTENT, new ZipContentCommand()); + allKnownCommandsMap.put(Operation.EXIT, new ExitCommand()); + } + + private CommandExecutor() { + } + + public static void execute(Operation operation) throws Exception { + allKnownCommandsMap.get(operation).execute(); + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/ConsoleHelper.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/ConsoleHelper.java new file mode 100644 index 0000000..426febb --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/ConsoleHelper.java @@ -0,0 +1,23 @@ +package com.javarush.task.task31.task3110; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +public class ConsoleHelper { + private static BufferedReader bis = new BufferedReader(new InputStreamReader(System.in)); + + public static void writeMessage(String message) { + System.out.println(message); + } + + public static String readString() throws IOException { + String text = bis.readLine(); + return text; + } + + public static int readInt() throws IOException { + String text = readString(); + return Integer.parseInt(text.trim()); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/FileManager.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/FileManager.java new file mode 100644 index 0000000..5228beb --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/FileManager.java @@ -0,0 +1,42 @@ +package com.javarush.task.task31.task3110; + +import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +public class FileManager { + private Path rootPath; + private List fileList; + + public FileManager(Path rootPath) throws IOException { + this.rootPath = rootPath; + this.fileList = new ArrayList<>(); + collectFileList(rootPath); + } + + public List getFileList() { + return fileList; + } + + private void collectFileList(Path path) throws IOException { + // Добавляем только файлы + if (Files.isRegularFile(path)) { + Path relativePath = rootPath.relativize(path); + fileList.add(relativePath); + } + + // Добавляем содержимое директории + if (Files.isDirectory(path)) { + // Рекурсивно проходимся по всему содержмому директории + // Чтобы не писать код по вызову close для DirectoryStream, обернем вызов newDirectoryStream в try-with-resources + try (DirectoryStream directoryStream = Files.newDirectoryStream(path)) { + for (Path file : directoryStream) { + collectFileList(file); + } + } + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/FileProperties.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/FileProperties.java new file mode 100644 index 0000000..e149dc5 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/FileProperties.java @@ -0,0 +1,55 @@ +package com.javarush.task.task31.task3110; + +public class FileProperties { + private String name; + private long size; + private long compressedSize; + private int compressionMethod; + + public FileProperties(String name, long size, long compressedSize, int compressionMethod) { + this.name = name; + this.size = size; + this.compressedSize = compressedSize; + this.compressionMethod = compressionMethod; + } + + + public String getName() { + return name; + } + + public long getSize() { + return size; + } + + public long getCompressedSize() { + return compressedSize; + } + + public int getCompressionMethod() { + return compressionMethod; + } + + public long getCompressionRatio() { + // Вычисляем степень сжатия + return 100 - ((compressedSize * 100) / size); + } + + @Override + public String toString() { + // Строим красивую строку из свойств + StringBuilder builder = new StringBuilder(); + builder.append(name); + if (size > 0) { + builder.append("\t"); + builder.append(size / 1024); + builder.append(" Kb ("); + builder.append(compressedSize / 1024); + builder.append(" Kb) сжатие: "); + builder.append(getCompressionRatio()); + builder.append("%"); + } + + return builder.toString(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/Operation.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/Operation.java new file mode 100644 index 0000000..21a6c66 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/Operation.java @@ -0,0 +1,10 @@ +package com.javarush.task.task31.task3110; + +public enum Operation { + CREATE, + ADD, + REMOVE, + EXTRACT, + CONTENT, + EXIT +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/ZipFileManager.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/ZipFileManager.java new file mode 100644 index 0000000..49daac4 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/ZipFileManager.java @@ -0,0 +1,230 @@ +package com.javarush.task.task31.task3110; + +import com.javarush.task.task31.task3110.exception.PathIsNotFoundException; +import com.javarush.task.task31.task3110.exception.WrongZipFileException; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; + +public class ZipFileManager { + // Полный путь zip файла + private final Path zipFile; + + public ZipFileManager(Path zipFile) { + this.zipFile = zipFile; + } + + public void createZip(Path source) throws Exception { + // Проверяем, существует ли директория, где будет создаваться архив + // При необходимости создаем ее + Path zipDirectory = zipFile.getParent(); + if (Files.notExists(zipDirectory)) + Files.createDirectories(zipDirectory); + + // Создаем zip поток + try (ZipOutputStream zipOutputStream = new ZipOutputStream(Files.newOutputStream(zipFile))) { + + if (Files.isDirectory(source)) { + // Если архивируем директорию, то нужно получить список файлов в ней + FileManager fileManager = new FileManager(source); + List fileNames = fileManager.getFileList(); + + // Добавляем каждый файл в архив + for (Path fileName : fileNames) + addNewZipEntry(zipOutputStream, source, fileName); + + } else if (Files.isRegularFile(source)) { + + // Если архивируем отдельный файл, то нужно получить его директорию и имя + addNewZipEntry(zipOutputStream, source.getParent(), source.getFileName()); + } else { + + // Если переданный source не директория и не файл, бросаем исключение + throw new PathIsNotFoundException(); + } + } + } + + public void extractAll(Path outputFolder) throws Exception { + // Проверяем существует ли zip файл + if (!Files.isRegularFile(zipFile)) { + throw new WrongZipFileException(); + } + + try (ZipInputStream zipInputStream = new ZipInputStream(Files.newInputStream(zipFile))) { + // Создаем директорию вывода, если она не существует + if (Files.notExists(outputFolder)) + Files.createDirectories(outputFolder); + + // Проходимся по содержимому zip потока (файла) + ZipEntry zipEntry = zipInputStream.getNextEntry(); + + while (zipEntry != null) { + String fileName = zipEntry.getName(); + Path fileFullName = outputFolder.resolve(fileName); + + // Создаем необходимые директории + Path parent = fileFullName.getParent(); + if (Files.notExists(parent)) + Files.createDirectories(parent); + + try (OutputStream outputStream = Files.newOutputStream(fileFullName)) { + copyData(zipInputStream, outputStream); + } + zipEntry = zipInputStream.getNextEntry(); + } + } + } + + public void removeFile(Path path) throws Exception { + removeFiles(Collections.singletonList(path)); + } + + public void removeFiles(List pathList) throws Exception { + // Проверяем существует ли zip файл + if (!Files.isRegularFile(zipFile)) { + throw new WrongZipFileException(); + } + + // Создаем временный файл + Path tempZipFile = Files.createTempFile(null, null); + + try (ZipOutputStream zipOutputStream = new ZipOutputStream(Files.newOutputStream(tempZipFile))) { + try (ZipInputStream zipInputStream = new ZipInputStream(Files.newInputStream(zipFile))) { + + ZipEntry zipEntry = zipInputStream.getNextEntry(); + while (zipEntry != null) { + + Path archivedFile = Paths.get(zipEntry.getName()); + + if (!pathList.contains(archivedFile)) { + String fileName = zipEntry.getName(); + zipOutputStream.putNextEntry(new ZipEntry(fileName)); + + copyData(zipInputStream, zipOutputStream); + + zipOutputStream.closeEntry(); + zipInputStream.closeEntry(); + } + else { + ConsoleHelper.writeMessage(String.format("Файл '%s' удален из архива.", archivedFile.toString())); + } + zipEntry = zipInputStream.getNextEntry(); + } + } + } + + // Перемещаем временный файл на место оригинального + Files.move(tempZipFile, zipFile, StandardCopyOption.REPLACE_EXISTING); + } + + public void addFile(Path absolutePath) throws Exception { + addFiles(Collections.singletonList(absolutePath)); + } + + public void addFiles(List absolutePathList) throws Exception { + // Проверяем существует ли zip файл + if (!Files.isRegularFile(zipFile)) { + throw new WrongZipFileException(); + } + + // Создаем временный файл + Path tempZipFile = Files.createTempFile(null, null); + List archiveFiles = new ArrayList<>(); + + try (ZipOutputStream zipOutputStream = new ZipOutputStream(Files.newOutputStream(tempZipFile))) { + try (ZipInputStream zipInputStream = new ZipInputStream(Files.newInputStream(zipFile))) { + + ZipEntry zipEntry = zipInputStream.getNextEntry(); + while (zipEntry != null) { + String fileName = zipEntry.getName(); + archiveFiles.add(Paths.get(fileName)); + + zipOutputStream.putNextEntry(new ZipEntry(fileName)); + copyData(zipInputStream, zipOutputStream); + + zipInputStream.closeEntry(); + zipOutputStream.closeEntry(); + + zipEntry = zipInputStream.getNextEntry(); + } + } + + // Архивируем новые файлы + for (Path file : absolutePathList) { + if (Files.isRegularFile(file)) + { + if (archiveFiles.contains(file.getFileName())) + ConsoleHelper.writeMessage(String.format("Файл '%s' уже существует в архиве.", file.toString())); + else { + addNewZipEntry(zipOutputStream, file.getParent(), file.getFileName()); + ConsoleHelper.writeMessage(String.format("Файл '%s' добавлен в архиве.", file.toString())); + } + } + else + throw new PathIsNotFoundException(); + } + } + + // Перемещаем временный файл на место оригинального + Files.move(tempZipFile, zipFile, StandardCopyOption.REPLACE_EXISTING); + } + + public List getFilesList() throws Exception { + // Проверяем существует ли zip файл + if (!Files.isRegularFile(zipFile)) { + throw new WrongZipFileException(); + } + + List files = new ArrayList<>(); + + try (ZipInputStream zipInputStream = new ZipInputStream(Files.newInputStream(zipFile))) { + ZipEntry zipEntry = zipInputStream.getNextEntry(); + + while (zipEntry != null) { + // Поля "размер" и "сжатый размер" не известны, пока элемент не будет прочитан + // Давайте вычитаем его в какой-то выходной поток + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + copyData(zipInputStream, baos); + + FileProperties file = new FileProperties(zipEntry.getName(), zipEntry.getSize(), zipEntry.getCompressedSize(), zipEntry.getMethod()); + files.add(file); + zipEntry = zipInputStream.getNextEntry(); + } + } + + return files; + } + + private void addNewZipEntry(ZipOutputStream zipOutputStream, Path filePath, Path fileName) throws Exception { + Path fullPath = filePath.resolve(fileName); + try (InputStream inputStream = Files.newInputStream(fullPath)) { + ZipEntry entry = new ZipEntry(fileName.toString()); + + zipOutputStream.putNextEntry(entry); + + copyData(inputStream, zipOutputStream); + + zipOutputStream.closeEntry(); + } + } + + private void copyData(InputStream in, OutputStream out) throws Exception { + byte[] buffer = new byte[8 * 1024]; + int len; + while ((len = in.read(buffer)) > 0) { + out.write(buffer, 0, len); + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/Command.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/Command.java new file mode 100644 index 0000000..6a51a10 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/Command.java @@ -0,0 +1,5 @@ +package com.javarush.task.task31.task3110.command; + +public interface Command { + void execute() throws Exception; +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ExitCommand.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ExitCommand.java new file mode 100644 index 0000000..31cf0d7 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ExitCommand.java @@ -0,0 +1,10 @@ +package com.javarush.task.task31.task3110.command; + +import com.javarush.task.task31.task3110.ConsoleHelper; + +public class ExitCommand implements Command { + @Override + public void execute() throws Exception { + ConsoleHelper.writeMessage("До встречи!"); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipAddCommand.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipAddCommand.java new file mode 100644 index 0000000..ad9911b --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipAddCommand.java @@ -0,0 +1,29 @@ +package com.javarush.task.task31.task3110.command; + +import com.javarush.task.task31.task3110.ConsoleHelper; +import com.javarush.task.task31.task3110.ZipFileManager; +import com.javarush.task.task31.task3110.exception.PathIsNotFoundException; + +import java.nio.file.Path; +import java.nio.file.Paths; + +public class ZipAddCommand extends ZipCommand { + @Override + public void execute() throws Exception { + try { + ConsoleHelper.writeMessage("Добавление нового файла в архив."); + + ZipFileManager zipFileManager = getZipFileManager(); + + ConsoleHelper.writeMessage("Введите полное имя файла для добавления:"); + Path sourcePath = Paths.get(ConsoleHelper.readString()); + + zipFileManager.addFile(sourcePath); + + ConsoleHelper.writeMessage("Добавление в архив завершено."); + + } catch (PathIsNotFoundException e) { + ConsoleHelper.writeMessage("Файл не был найден."); + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipCommand.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipCommand.java new file mode 100644 index 0000000..bb31975 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipCommand.java @@ -0,0 +1,16 @@ +package com.javarush.task.task31.task3110.command; + +import com.javarush.task.task31.task3110.ConsoleHelper; +import com.javarush.task.task31.task3110.ZipFileManager; + +import java.nio.file.Path; +import java.nio.file.Paths; + +public abstract class ZipCommand implements Command { + + public ZipFileManager getZipFileManager() throws Exception{ + ConsoleHelper.writeMessage("Введите полный путь файла архива:"); + Path zipPath = Paths.get(ConsoleHelper.readString()); + return new ZipFileManager(zipPath); + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipContentCommand.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipContentCommand.java new file mode 100644 index 0000000..9b7c5c9 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipContentCommand.java @@ -0,0 +1,25 @@ +package com.javarush.task.task31.task3110.command; + +import com.javarush.task.task31.task3110.ConsoleHelper; +import com.javarush.task.task31.task3110.FileProperties; +import com.javarush.task.task31.task3110.ZipFileManager; + +import java.util.List; + +public class ZipContentCommand extends ZipCommand { + @Override + public void execute() throws Exception { + ConsoleHelper.writeMessage("Просмотр содержимого архива."); + + ZipFileManager zipFileManager = getZipFileManager(); + + ConsoleHelper.writeMessage("Содержимое архива:"); + + List files = zipFileManager.getFilesList(); + for (FileProperties file : files) { + ConsoleHelper.writeMessage(file.toString()); + } + + ConsoleHelper.writeMessage("Содержимое архива прочитано."); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipCreateCommand.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipCreateCommand.java new file mode 100644 index 0000000..c775d66 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipCreateCommand.java @@ -0,0 +1,28 @@ +package com.javarush.task.task31.task3110.command; + +import com.javarush.task.task31.task3110.ConsoleHelper; +import com.javarush.task.task31.task3110.ZipFileManager; +import com.javarush.task.task31.task3110.exception.PathIsNotFoundException; + +import java.nio.file.Path; +import java.nio.file.Paths; + +public class ZipCreateCommand extends ZipCommand { + @Override + public void execute() throws Exception { + try { + ConsoleHelper.writeMessage("Создание архива."); + + ZipFileManager zipFileManager = getZipFileManager(); + + ConsoleHelper.writeMessage("Введите полное имя файла или директории для архивации:"); + Path sourcePath = Paths.get(ConsoleHelper.readString()); + zipFileManager.createZip(sourcePath); + + ConsoleHelper.writeMessage("Архив создан."); + + } catch (PathIsNotFoundException e) { + ConsoleHelper.writeMessage("Вы неверно указали имя файла или директории."); + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipExtractCommand.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipExtractCommand.java new file mode 100644 index 0000000..2da2667 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipExtractCommand.java @@ -0,0 +1,28 @@ +package com.javarush.task.task31.task3110.command; + +import com.javarush.task.task31.task3110.ConsoleHelper; +import com.javarush.task.task31.task3110.ZipFileManager; +import com.javarush.task.task31.task3110.exception.PathIsNotFoundException; + +import java.nio.file.Path; +import java.nio.file.Paths; + +public class ZipExtractCommand extends ZipCommand { + @Override + public void execute() throws Exception { + try { + ConsoleHelper.writeMessage("Распаковка архива."); + + ZipFileManager zipFileManager = getZipFileManager(); + + ConsoleHelper.writeMessage("Введите путь для распаковки:"); + Path destinationPath = Paths.get(ConsoleHelper.readString()); + zipFileManager.extractAll(destinationPath); + + ConsoleHelper.writeMessage("Архив был распакован."); + + } catch (PathIsNotFoundException e) { + ConsoleHelper.writeMessage("Неверный путь для распаковки."); + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipRemoveCommand.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipRemoveCommand.java new file mode 100644 index 0000000..4db7635 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/command/ZipRemoveCommand.java @@ -0,0 +1,22 @@ +package com.javarush.task.task31.task3110.command; + +import com.javarush.task.task31.task3110.ConsoleHelper; +import com.javarush.task.task31.task3110.ZipFileManager; + +import java.nio.file.Path; +import java.nio.file.Paths; + +public class ZipRemoveCommand extends ZipCommand { + @Override + public void execute() throws Exception { + ConsoleHelper.writeMessage("Удаление файла из архива."); + + ZipFileManager zipFileManager = getZipFileManager(); + + ConsoleHelper.writeMessage("Введите полный путь файла в архиве:"); + Path sourcePath = Paths.get(ConsoleHelper.readString()); + zipFileManager.removeFile(sourcePath); + + ConsoleHelper.writeMessage("Удаление из архива завершено."); + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/exception/PathIsNotFoundException.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/exception/PathIsNotFoundException.java new file mode 100644 index 0000000..614e886 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/exception/PathIsNotFoundException.java @@ -0,0 +1,4 @@ +package com.javarush.task.task31.task3110.exception; + +public class PathIsNotFoundException extends Exception { +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/exception/WrongZipFileException.java b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/exception/WrongZipFileException.java new file mode 100644 index 0000000..e28d88c --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/exception/WrongZipFileException.java @@ -0,0 +1,4 @@ +package com.javarush.task.task31.task3110.exception; + +public class WrongZipFileException extends Exception { +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task31/task3110/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..2943cff --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task31/task3110/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,144 @@ +taskKey="com.javarush.task.task31.task3110.big18" + +Archiver (18) + +Ты отличный ученик, я немного подправил твой код, можешь использовать этот архиватор для архивации +в повседневной жизни. Если будет время и желание, попробуй добавить операцию изменения степени +сжатия архива! + + +Требования: +1. Архиватор готов. + + +Archiver (17) + +Осталась ерунда. Добавить добавление файла в архив. Звучит подозрительно, но именно этим мы и +займемся. Добавление файлов похоже на удаление, мы создаем временный файл архив, переписываем в +него все содержимое старого архива и добавляем новые файлы. Потом заменяем старый файл архива +новым. +1. Добавь публичный метод void addFiles(List absolutePathList) throws Exception в класс +ZipFileManager, где absolutePathList – список абсолютных путей добавляемых файлов. Этот метод +должен: +1.1. Как обычно, бросать исключение WrongZipFileException, если файл архива не существует +1.2. Создать временный файл архива +1.3. Пройти по всем файлам оригинального архива, переписать каждый файл в новый архив, +добавить имя переписанного файла в какой-нибудь локальный список. +1.4. Пройтись по списку добавляемых файлов. +1.5. Для каждого файла проверить, есть ли он на диске и является ли он обычным файлом, +если что-то не так, кинь исключение PathIsNotFoundException() +1.6. Проверить, есть ли добавляемый файл уже в архиве (используй список из п.1.3). Такое +возможно, если пользователь уже когда-то добавлял его. +- Если файла нет в списке, добавь его в новый архив, выведи сообщение, что такой-то файл +добавлен в архив +- Если файл есть в списке, просто сообщи пользователю, что такой файл уже есть в архиве +1.7. Заменить оригинальный файл архива временным, в котором уже есть добавленные +файлы. +2. Добавь публичный метод void addFile(Path absolutePath) throws Exception в класс ZipFileManager, +реализуй его с помощью вызова метода addFiles(), аналогично тому, как мы это делали для +удаления файла. +3. Реализуй метод execute() класса ZipAddCommand: все как обычно, но не забудь спросить у +пользователя в какой архив и какой файл он хочет добавить, обработай исключение +PathIsNotFoundException, которое может кинуть метод addFile(). +4. Запусти программу и проверить, что добавление файла теперь работает. + + + +Archiver (16) + +Пришло время что-нибудь удалить из архива. Архив очень хитрая штука, нельзя вот так просто взять и +удалить какой-то элемент внутри него. +Почему? Представь, что мы решили сами придумать свой алгоритм сжатия текста. Посмотрев исходный +текст, мы видим, что в нем часто встречается фраза "быть программистом круто". Мы можем в месте, где +второй, третий, N-ый раз встречается наша фраза сделать пометку, что тут была фраза, как в строке S +начиная с символа номер K и длиной N, а саму фразу удалить. Когда мы заменим много повторяющихся +фраз, текст заметно сократится, но станет нечитаемым для тех, кто не знаком с нашим алгоритмом сжатия. +Мы же этот текст сможем восстановить (разархивировать). А теперь представь, что нам нужно удалить +часть текста, на которую ссылались сжатые фрагменты. В такой ситуации, весь наш архив перестанет +иметь смысл. Вот почему нельзя просто так удалить часть архива. Это очень примерное описание +варианта архивации, в реальности все намного сложнее. +Поэтому, чтобы что-то удалить из архива, нужно создать новый архив, переписать в него все, кроме +удаляемых файлов, а потом заменить старый архив вновь созданным. +1. Добавь публичный метод для удаления файлов из архива void removeFiles(List pathList) +throws Exception в класс ZipFileManager. В pathList будет передаваться список относительных путей на +файлы внутри архива. Он должен: +1.1. Бросать исключение WrongZipFileException, если файл архива не существует +1.2. Создать временный файл архива с помощью метода createTempFile() класса Files +1.3. Пройтись по всем файлам оригинального архива, проверить, есть ли текущий файл в списке +на удаление. +- Если файл есть в списке, вывести сообщение, что мы удалили файл с таким-то именем и +перейти к следующему файлу. +- Если файла нет в списке на удаление, переписать его в новый архив +1.4. Заменить оригинальный файл архива временным, в который мы записали нужные файлы. +Это нужно сделать с помощью метода move() класса Files +2. Добавь публичный метод void removeFile(Path path) throws Exception в класс ZipFileManager, +который будет вызывать метод removeFiles, создавая список из одного элемента. Это можно сделать с помощью +метода singletonList() класса Collections. Посмотри, как он работает. +3. Реализуй метод execute() класса ZipRemoveCommand, создав объект класса ZipFileManager, +спросив пользователя из какого архива и какой файл будем удалять, и вызвав метод removeFile(). +Все остальное, как и в других командах. Исключение PathIsNotFoundException можно не ловить, т.к. метод +removeFile() не должен его кидать. +4. Запусти программу и проверить, что удаление файла из архива работает. + + + +Archiver (15) + +Пора попробовать что-нибудь распаковать. Для этого добавим публичный метод void extractAll(Path +outputFolder) throws Exception в класс ZipFileManager. Path outputFolder - это путь, куда мы будем +распаковывать наш архив. У тебя уже большой опыт работы с элементами архива и потоками. Так что, я +дам только подсказки по реализации этого метода, а тебе придется хорошенько подумать, как это все +сделать: +1. Проверь, есть ли zip файл вообще +2. Если директория outputFolder не существует, то ее нужно создать, как и все папки, внутри которых +она лежит. +3. Внутри архива некоторые файлы могут лежат внутри папок, тогда метод getName() элемента +архива ZipEntry, вернет не совсем имя, как может показаться из названия, а относительный путь +внутри архива. Этот относительный путь должен сохраниться и после распаковки, но уже +относительно той директории, куда мы распаковали архив +4. Реализуй метод execute() класса ZipExtractCommand, по аналогии с таким же методом класса +ZipCreateCommand, сделай такой же блок try-catch, только поменяй сообщения выводимые +пользователю, чтобы он понял, что сейчас мы будем распаковывать архив, и что нужно ввести +полное имя архива и директорию, куда будем распаковывать. Не забудь вызвать метод extractAll +класса ZipFileManager, а не createZip, как это было в ZipCreateCommand +5. Запускай программу и наслаждайся результатом распаковки + + + +Archiver (14) + +Все готово, чтобы реализовать метод execute() класса ZipContentCommand: +1. Выведи сообщение "Просмотр содержимого архива." +2. Создай объект класса ZipFileManager с помощью метода getZipFileManager() +3. Выведи сообщение "Содержимое архива:" +4. Получи список файлов архива с помощью метода getFilesList() +5. Выведи свойства каждого файла в консоль. Тут нам и пригодится ранее реализованный метод +toString() класса FileProperties +6. Выведи сообщение "Содержимое архива прочитано." +7. Запусти программу и проверь, что команда "просмотреть содержимое архива" работает + + + +Archiver (13) + +Продолжим наш путь к получению содержимого файла архива. Напишем метод getFilesList() в классе +ZipFileManager. Он будет возвращать список файлов в архиве, вернее список свойств этих файлов (класс +свойств FileProperties мы уже реализовали). Итак: +1. Добавь метод List getFilesList() throws Exception в класс ZipFileManager +2. Внутри метода проверь является ли содержимое zipFile обычным файлом с помощью +подходящего метода класса Files. Если это не файл, брось исключение WrongZipFileException(). +3. Создай список с элементами типа FileProperties, в него мы будем складывать свойства файлов +4. Создай входящий поток ZipInputStream, для файла из переменной zipFile. Как и в прошлые разы, оберни его создание +в try-with-resources +5. Пройдись по всем элементам ZipEntry потока ZipInputStream +6. Для каждого элемента ZipEntry вычитай его содержимое, иначе у нас не будет информации о его +размере. Нельзя узнать размер файла в архиве, не вычитав его. Это очень легко сделать с +помощью функции copyData, используя временный буфер типа ByteArrayOutputStream. +7. Получи имя, размер, сжатый размер и метод сжатия элемента архива. Посмотри, что еще можно +узнать о нем. +8. Создай объект класса FileProperties, используя полученные данные о файле. +9. Добавь созданный объект из п.8 в список из п.3 +10. После выхода из цикла верни собранную информацию вызвавшему методу. + + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/Controller.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/Controller.java new file mode 100644 index 0000000..5687b9c --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/Controller.java @@ -0,0 +1,144 @@ +package com.javarush.task.task32.task3209; + +import com.javarush.task.task32.task3209.listeners.UndoListener; + +import javax.swing.*; +import javax.swing.event.DocumentListener; +import javax.swing.text.BadLocationException; +import javax.swing.text.html.HTMLDocument; +import javax.swing.text.html.HTMLEditorKit; +import java.io.*; + +/** + * Created by ArchMage on 07.04.17. + */ +public class Controller { + private View view; + private HTMLDocument document; + private File currentFile; + + public void init(){ + createNewDocument(); + } + + public HTMLDocument getDocument() { + return document; + } + + public void resetDocument(){ + if (document != null) { + document.removeUndoableEditListener(view.getUndoListener()); + } + document = (HTMLDocument) new HTMLEditorKit().createDefaultDocument(); + document.addUndoableEditListener(view.getUndoListener()); + view.update(); + } + + public void exit(){ + System.exit(0); + } + + public Controller(View view) { + this.view = view; + } + + public void setPlainText(String text){ + resetDocument(); + StringReader reader = new StringReader(text); + try { + new HTMLEditorKit().read(reader, document, 0); + } catch (IOException e) { + ExceptionHandler.log(e); + } catch (BadLocationException e) { + ExceptionHandler.log(e); + } + } + + public String getPlainText(){ + StringWriter writer = new StringWriter(); + try { + new HTMLEditorKit().write(writer, document, 0, document.getLength()); + } catch (IOException e) { + ExceptionHandler.log(e); + } catch (BadLocationException e) { + ExceptionHandler.log(e); + } + return writer.toString(); + } + + public void createNewDocument(){ + view.selectHtmlTab(); + resetDocument(); + view.setTitle("HTML редактор"); + view.resetUndo(); + currentFile = null; + + } + + public void saveDocumentAs(){ + view.selectHtmlTab(); + JFileChooser fileChooser = new JFileChooser(); + fileChooser.setFileFilter(new HTMLFileFilter()); + int choose = fileChooser.showSaveDialog(view); + if (choose == JFileChooser.APPROVE_OPTION) { + currentFile = fileChooser.getSelectedFile(); + view.setTitle(currentFile.getName()); + try { + FileWriter writer = new FileWriter(currentFile); + new HTMLEditorKit().write(writer, document, 0, document.getLength()); + } catch (IOException e) { + ExceptionHandler.log(e); + } catch (BadLocationException e) { + ExceptionHandler.log(e); + } + } + } + + public void saveDocument(){ + if (currentFile == null){ + saveDocumentAs(); + } else { + view.selectHtmlTab(); + view.setTitle(currentFile.getName()); + try { + FileWriter writer = new FileWriter(currentFile); + new HTMLEditorKit().write(writer, document, 0, document.getLength()); + } catch (IOException e) { + ExceptionHandler.log(e); + } catch (BadLocationException e) { + ExceptionHandler.log(e); + } + } + } + + public void openDocument(){ + view.selectHtmlTab(); + JFileChooser chooser = new JFileChooser(); + chooser.setFileFilter(new HTMLFileFilter()); + int option = chooser.showOpenDialog(view); + if (option == JFileChooser.APPROVE_OPTION){ + currentFile = chooser.getSelectedFile(); + resetDocument(); + view.setTitle(currentFile.getName()); + try { + FileReader reader = new FileReader(currentFile); + new HTMLEditorKit().read(reader, document, 0); + view.resetUndo(); + } catch (FileNotFoundException e) { + ExceptionHandler.log(e); + } catch (BadLocationException e) { + ExceptionHandler.log(e); + } catch (IOException e) { + ExceptionHandler.log(e); + } + } + } + + public static void main(String[] args){ + View view = new View(); + Controller controller = new Controller(view); + view.setController(controller); + view.init(); + controller.init(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/ExceptionHandler.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/ExceptionHandler.java new file mode 100644 index 0000000..be9ad01 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/ExceptionHandler.java @@ -0,0 +1,11 @@ +package com.javarush.task.task32.task3209; + +/** + * Created by ArchMage on 07.04.17. + */ +public class ExceptionHandler { + + public static void log(Exception e){ + System.out.println(e.toString()); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/HTMLFileFilter.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/HTMLFileFilter.java new file mode 100644 index 0000000..bb00e90 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/HTMLFileFilter.java @@ -0,0 +1,31 @@ +package com.javarush.task.task32.task3209; + +import javax.swing.filechooser.FileFilter; +import java.io.File; + + +/** + * Created by ArchMage on 10.04.17. + */ +public class HTMLFileFilter extends FileFilter { + + + @Override + public boolean accept(File f) { + if (!f.isDirectory()) { + String fileName = f.getName(); + fileName = fileName.toLowerCase(); + if (fileName.endsWith(".html") || fileName.endsWith(".htm")) { + return true; + } else { + return false; + } + } + else { return true; } + } + + @Override + public String getDescription() { + return "HTML и HTM файлы"; + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/MenuHelper.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/MenuHelper.java new file mode 100644 index 0000000..c115e7f --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/MenuHelper.java @@ -0,0 +1,132 @@ +package com.javarush.task.task32.task3209; + +import com.javarush.task.task32.task3209.actions.*; +import com.javarush.task.task32.task3209.listeners.TextEditMenuListener; +import com.javarush.task.task32.task3209.listeners.UndoMenuListener; + +import javax.swing.*; +import javax.swing.text.DefaultEditorKit; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyledEditorKit; +import java.awt.*; +import java.awt.event.ActionListener; + +public class MenuHelper { + public static JMenuItem addMenuItem(JMenu parent, String text, ActionListener actionListener) { + JMenuItem menuItem = new JMenuItem(text); + menuItem.addActionListener(actionListener); + parent.add(menuItem); + return menuItem; + } + + public static JMenuItem addMenuItem(JMenu parent, String text, Action action) { + JMenuItem menuItem = addMenuItem(parent, action); + menuItem.setText(text); + return menuItem; + } + + public static JMenuItem addMenuItem(JMenu parent, Action action) { + JMenuItem menuItem = new JMenuItem(action); + parent.add(menuItem); + return menuItem; + } + + public static void initHelpMenu(View view, JMenuBar menuBar) { + JMenu helpMenu = new JMenu("Помощь"); + menuBar.add(helpMenu); + + addMenuItem(helpMenu, "О программе", view); + } + + public static void initFontMenu(View view, JMenuBar menuBar) { + JMenu fontMenu = new JMenu("Шрифт"); + menuBar.add(fontMenu); + + JMenu fontTypeMenu = new JMenu("Шрифт"); + fontMenu.add(fontTypeMenu); + + String[] fontTypes = {Font.SANS_SERIF, Font.SERIF, Font.MONOSPACED, Font.DIALOG, Font.DIALOG_INPUT}; + for (String fontType : fontTypes) { + addMenuItem(fontTypeMenu, fontType, new StyledEditorKit.FontFamilyAction(fontType, fontType)); + } + + JMenu fontSizeMenu = new JMenu("Размер шрифта"); + fontMenu.add(fontSizeMenu); + + String[] fontSizes = {"6", "8", "10", "12", "14", "16", "20", "24", "32", "36", "48", "72"}; + for (String fontSize : fontSizes) { + addMenuItem(fontSizeMenu, fontSize, new StyledEditorKit.FontSizeAction(fontSize, Integer.parseInt(fontSize))); + } + + fontMenu.addMenuListener(new TextEditMenuListener(view)); + } + + public static void initColorMenu(View view, JMenuBar menuBar) { + JMenu colorMenu = new JMenu("Цвет"); + menuBar.add(colorMenu); + + addMenuItem(colorMenu, new StyledEditorKit.ForegroundAction("Красный", Color.red)); + addMenuItem(colorMenu, new StyledEditorKit.ForegroundAction("Оранжевый", Color.orange)); + addMenuItem(colorMenu, new StyledEditorKit.ForegroundAction("Желтый", Color.yellow)); + addMenuItem(colorMenu, new StyledEditorKit.ForegroundAction("Зеленый", Color.green)); + addMenuItem(colorMenu, new StyledEditorKit.ForegroundAction("Синий", Color.blue)); + addMenuItem(colorMenu, new StyledEditorKit.ForegroundAction("Голубой", Color.cyan)); + addMenuItem(colorMenu, new StyledEditorKit.ForegroundAction("Пурпурный", Color.magenta)); + addMenuItem(colorMenu, new StyledEditorKit.ForegroundAction("Черный", Color.black)); + + colorMenu.addMenuListener(new TextEditMenuListener(view)); + } + + public static void initAlignMenu(View view, JMenuBar menuBar) { + JMenu alignMenu = new JMenu("Выравнивание"); + menuBar.add(alignMenu); + + addMenuItem(alignMenu, new StyledEditorKit.AlignmentAction("По левому краю", StyleConstants.ALIGN_LEFT)); + addMenuItem(alignMenu, new StyledEditorKit.AlignmentAction("По центру", StyleConstants.ALIGN_CENTER)); + addMenuItem(alignMenu, new StyledEditorKit.AlignmentAction("По правому краю", StyleConstants.ALIGN_RIGHT)); + + alignMenu.addMenuListener(new TextEditMenuListener(view)); + } + + public static void initStyleMenu(View view, JMenuBar menuBar) { + JMenu styleMenu = new JMenu("Стиль"); + menuBar.add(styleMenu); + + addMenuItem(styleMenu, "Полужирный", new StyledEditorKit.BoldAction()); + addMenuItem(styleMenu, "Подчеркнутый", new StyledEditorKit.UnderlineAction()); + addMenuItem(styleMenu, "Курсив", new StyledEditorKit.ItalicAction()); + + styleMenu.addSeparator(); + + addMenuItem(styleMenu, "Подстрочный знак", new SubscriptAction()); + addMenuItem(styleMenu, "Надстрочный знак", new SuperscriptAction()); + addMenuItem(styleMenu, "Зачеркнутый", new StrikeThroughAction()); + + styleMenu.addMenuListener(new TextEditMenuListener(view)); + } + + public static void initEditMenu(View view, JMenuBar menuBar) { + JMenu editMenu = new JMenu("Редактировать"); + menuBar.add(editMenu); + + JMenuItem undoItem = addMenuItem(editMenu, "Отменить", new UndoAction(view)); + JMenuItem redoItem = addMenuItem(editMenu, "Вернуть", new RedoAction(view)); + addMenuItem(editMenu, "Вырезать", new DefaultEditorKit.CutAction()); + addMenuItem(editMenu, "Копировать", new DefaultEditorKit.CopyAction()); + addMenuItem(editMenu, "Вставить", new DefaultEditorKit.PasteAction()); + + editMenu.addMenuListener(new UndoMenuListener(view, undoItem, redoItem)); + } + + public static void initFileMenu(View view, JMenuBar menuBar) { + JMenu fileMenu = new JMenu("Файл"); + menuBar.add(fileMenu); + + addMenuItem(fileMenu, "Новый", view); + addMenuItem(fileMenu, "Открыть", view); + addMenuItem(fileMenu, "Сохранить", view); + addMenuItem(fileMenu, "Сохранить как...", view); + fileMenu.addSeparator(); + addMenuItem(fileMenu, "Выход", view); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/View.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/View.java new file mode 100644 index 0000000..afabdfa --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/View.java @@ -0,0 +1,170 @@ +package com.javarush.task.task32.task3209; + +import com.javarush.task.task32.task3209.listeners.FrameListener; +import com.javarush.task.task32.task3209.listeners.TabbedPaneChangeListener; +import com.javarush.task.task32.task3209.listeners.UndoListener; + +import javax.swing.*; +import javax.swing.text.html.HTMLDocument; +import javax.swing.undo.UndoManager; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * Created by ArchMage on 07.04.17. + */ +public class View extends JFrame implements ActionListener { + private Controller controller; + private JTabbedPane tabbedPane = new JTabbedPane(); + private JTextPane htmlTextPane = new JTextPane(); + private JEditorPane plainTextPane = new JEditorPane(); + private UndoManager undoManager = new UndoManager(); + private UndoListener undoListener = new UndoListener(undoManager); + + public View(){ + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (ClassNotFoundException e) { + ExceptionHandler.log(e); + } catch (InstantiationException e) { + ExceptionHandler.log(e); + } catch (IllegalAccessException e) { + ExceptionHandler.log(e); + } catch (UnsupportedLookAndFeelException e) { + ExceptionHandler.log(e); + } + } + + public void init(){ + initGui(); + FrameListener frameListener = new FrameListener(this); + addWindowListener(frameListener); + setVisible(true); + } + + public void selectedTabChanged(){ + if (tabbedPane.getSelectedIndex() == 0) { + controller.setPlainText(plainTextPane.getText()); + } else { + plainTextPane.setText(controller.getPlainText()); + } + resetUndo(); + } + + public void initMenuBar(){ + JMenuBar menuBar = new JMenuBar(); + MenuHelper.initFileMenu(this, menuBar); + MenuHelper.initEditMenu(this, menuBar); + MenuHelper.initStyleMenu(this, menuBar); + MenuHelper.initAlignMenu(this, menuBar); + MenuHelper.initColorMenu(this, menuBar); + MenuHelper.initFontMenu(this, menuBar); + MenuHelper.initHelpMenu(this, menuBar); + getContentPane().add(menuBar, BorderLayout.NORTH); + + } + + public void initEditor(){ + Dimension d = new Dimension(800, 500); + htmlTextPane.setContentType("text/html"); + JScrollPane scrollHtml = new JScrollPane(htmlTextPane); + tabbedPane.addTab("HTML" ,scrollHtml); + plainTextPane.setContentType("text/html"); + JScrollPane scrollText = new JScrollPane(plainTextPane); + tabbedPane.addTab("Текст", scrollText); + tabbedPane.setPreferredSize(d); + TabbedPaneChangeListener tabChangeListener = new TabbedPaneChangeListener(this); + tabbedPane.addChangeListener(tabChangeListener); + this.getContentPane().add(tabbedPane, BorderLayout.CENTER); + } + + public void initGui(){ + initMenuBar(); + initEditor(); + pack(); + } + + public UndoListener getUndoListener() { + return undoListener; + } + + public void resetUndo(){ + undoManager.discardAllEdits(); + } + + public void exit(){ + controller.exit(); + } + + public Controller getController() { + return controller; + } + + public void setController(Controller controller) { + this.controller = controller; + } + + public boolean canUndo(){ + return undoManager.canUndo(); + } + + public boolean canRedo(){ + return undoManager.canRedo(); + } + + public void undo(){ + try { + undoManager.undo(); + } catch (Exception e){ + ExceptionHandler.log(e); + } + } + + public void redo(){ + try{ + undoManager.redo(); + } catch (Exception e){ + ExceptionHandler.log(e); + } + } + + public boolean isHtmlTabSelected(){ + if (tabbedPane.getSelectedIndex() == 0) { return true; } + else {return false;} + } + + public void selectHtmlTab(){ + tabbedPane.setSelectedIndex(0); + resetUndo(); + } + + public void update(){ + HTMLDocument document = controller.getDocument(); + selectHtmlTab(); + htmlTextPane.setDocument(document); + } + + public void showAbout(){ + JOptionPane.showMessageDialog(this, "Сообщение", "Текст сообщения", JOptionPane.INFORMATION_MESSAGE); + } + + + @Override + public void actionPerformed(ActionEvent e) { + String action = e.getActionCommand(); + if ("Новый".equals(action)) { + controller.createNewDocument(); + }else if ("Открыть".equals(action)){ + controller.openDocument(); + }else if ("Сохранить".equals(action)){ + controller.saveDocument(); + }else if ("Сохранить как...".equals(action)){ + controller.saveDocumentAs(); + }else if ("Выход".equals(action)){ + controller.exit(); + }else if ("О программе".equals(action)){ + showAbout(); + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/RedoAction.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/RedoAction.java new file mode 100644 index 0000000..b7fc221 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/RedoAction.java @@ -0,0 +1,22 @@ +package com.javarush.task.task32.task3209.actions; + +import com.javarush.task.task32.task3209.View; + +import javax.swing.*; +import java.awt.event.ActionEvent; + +/** + * Created by ArchMage on 07.04.17. + */ +public class RedoAction extends AbstractAction { + private View view; + + public RedoAction(View view) { + this.view = view; + } + + @Override + public void actionPerformed(ActionEvent e) { + view.redo(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/StrikeThroughAction.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/StrikeThroughAction.java new file mode 100644 index 0000000..12c8f70 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/StrikeThroughAction.java @@ -0,0 +1,25 @@ +package com.javarush.task.task32.task3209.actions; + +import javax.swing.*; +import javax.swing.text.MutableAttributeSet; +import javax.swing.text.SimpleAttributeSet; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyledEditorKit; +import java.awt.event.ActionEvent; + +public class StrikeThroughAction extends StyledEditorKit.StyledTextAction { + + public StrikeThroughAction() { + super(StyleConstants.StrikeThrough.toString()); + } + + public void actionPerformed(ActionEvent actionEvent) { + JEditorPane editor = getEditor(actionEvent); + if (editor != null) { + MutableAttributeSet mutableAttributeSet = getStyledEditorKit(editor).getInputAttributes(); + SimpleAttributeSet simpleAttributeSet = new SimpleAttributeSet(); + StyleConstants.setStrikeThrough(simpleAttributeSet, !StyleConstants.isStrikeThrough(mutableAttributeSet)); + setCharacterAttributes(editor, simpleAttributeSet, false); + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/SubscriptAction.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/SubscriptAction.java new file mode 100644 index 0000000..6c137ca --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/SubscriptAction.java @@ -0,0 +1,29 @@ +package com.javarush.task.task32.task3209.actions; + +import javax.swing.*; +import javax.swing.text.MutableAttributeSet; +import javax.swing.text.SimpleAttributeSet; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyledEditorKit; +import java.awt.event.ActionEvent; + +/** + * Created by ArchMage on 07.04.17. + */ +public class SubscriptAction extends StyledEditorKit.StyledTextAction { + + public SubscriptAction() { + super(StyleConstants.Subscript.toString()); + } + + @Override + public void actionPerformed(ActionEvent e) { + JEditorPane editor = getEditor(e); + if (editor != null) { + MutableAttributeSet mutableAttributeSet = getStyledEditorKit(editor).getInputAttributes(); + SimpleAttributeSet simpleAttributeSet = new SimpleAttributeSet(); + StyleConstants.setSubscript(simpleAttributeSet, !StyleConstants.isSubscript(mutableAttributeSet)); + setCharacterAttributes(editor, simpleAttributeSet, false); + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/SuperscriptAction.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/SuperscriptAction.java new file mode 100644 index 0000000..df2242a --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/SuperscriptAction.java @@ -0,0 +1,29 @@ +package com.javarush.task.task32.task3209.actions; + +import javax.swing.*; +import javax.swing.text.MutableAttributeSet; +import javax.swing.text.SimpleAttributeSet; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyledEditorKit; +import java.awt.event.ActionEvent; + +/** + * Created by ArchMage on 07.04.17. + */ +public class SuperscriptAction extends StyledEditorKit.StyledTextAction { + + public SuperscriptAction() { + super(StyleConstants.Superscript.toString()); + } + + @Override + public void actionPerformed(ActionEvent e) { + JEditorPane editor = getEditor(e); + if (editor != null) { + MutableAttributeSet mutableAttributeSet = getStyledEditorKit(editor).getInputAttributes(); + SimpleAttributeSet simpleAttributeSet = new SimpleAttributeSet(); + StyleConstants.setSuperscript(simpleAttributeSet, !StyleConstants.isSuperscript(mutableAttributeSet)); + setCharacterAttributes(editor, simpleAttributeSet, false); + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/UndoAction.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/UndoAction.java new file mode 100644 index 0000000..68d85b2 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/actions/UndoAction.java @@ -0,0 +1,22 @@ +package com.javarush.task.task32.task3209.actions; + +import com.javarush.task.task32.task3209.View; + +import javax.swing.*; +import java.awt.event.ActionEvent; + +/** + * Created by ArchMage on 07.04.17. + */ +public class UndoAction extends AbstractAction { + private View view; + + public UndoAction(View view) { + this.view = view; + } + + @Override + public void actionPerformed(ActionEvent e) { + view.undo(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/FrameListener.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/FrameListener.java new file mode 100644 index 0000000..1b4e41d --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/FrameListener.java @@ -0,0 +1,22 @@ +package com.javarush.task.task32.task3209.listeners; + +import com.javarush.task.task32.task3209.View; + +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +/** + * Created by ArchMage on 07.04.17. + */ +public class FrameListener extends WindowAdapter { + private View view; + + public FrameListener(View view) { + this.view = view; + } + + @Override + public void windowClosing(WindowEvent e) { + view.exit(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/TabbedPaneChangeListener.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/TabbedPaneChangeListener.java new file mode 100644 index 0000000..652eb6a --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/TabbedPaneChangeListener.java @@ -0,0 +1,22 @@ +package com.javarush.task.task32.task3209.listeners; + +import com.javarush.task.task32.task3209.View; + +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +/** + * Created by ArchMage on 07.04.17. + */ +public class TabbedPaneChangeListener implements ChangeListener { + private View view; + + public TabbedPaneChangeListener(View view) { + this.view = view; + } + + @Override + public void stateChanged(ChangeEvent e) { + view.selectedTabChanged(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/TextEditMenuListener.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/TextEditMenuListener.java new file mode 100644 index 0000000..75d45b2 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/TextEditMenuListener.java @@ -0,0 +1,39 @@ +package com.javarush.task.task32.task3209.listeners; + +import com.javarush.task.task32.task3209.View; + +import javax.swing.*; +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuListener; +import java.awt.*; + +/** + * Created by ArchMage on 07.04.17. + */ +public class TextEditMenuListener implements MenuListener { + private View view; + + public TextEditMenuListener(View view){ + this.view = view; + } + + @Override + public void menuSelected(MenuEvent e) { + JMenu editObject = (JMenu) e.getSource(); + Component[] menuList = editObject.getMenuComponents(); + boolean isEnable = view.isHtmlTabSelected(); + for (Component entry : menuList){ + entry.setEnabled(isEnable); + } + } + + @Override + public void menuDeselected(MenuEvent e) { + + } + + @Override + public void menuCanceled(MenuEvent e) { + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/UndoListener.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/UndoListener.java new file mode 100644 index 0000000..d5c4242 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/UndoListener.java @@ -0,0 +1,21 @@ +package com.javarush.task.task32.task3209.listeners; + +import javax.swing.event.UndoableEditEvent; +import javax.swing.event.UndoableEditListener; +import javax.swing.undo.UndoManager; + +/** + * Created by ArchMage on 10.04.17. + */ +public class UndoListener implements UndoableEditListener { + private UndoManager undoManager; + + public UndoListener(UndoManager undoManager) { + this.undoManager = undoManager; + } + + @Override + public void undoableEditHappened(UndoableEditEvent e) { + undoManager.addEdit(e.getEdit()); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/UndoMenuListener.java b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/UndoMenuListener.java new file mode 100644 index 0000000..185f3ea --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/listeners/UndoMenuListener.java @@ -0,0 +1,49 @@ +package com.javarush.task.task32.task3209.listeners; + +import com.javarush.task.task32.task3209.View; + +import javax.swing.*; +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuListener; + +/** + * Created by ArchMage on 07.04.17. + */ +public class UndoMenuListener implements MenuListener { + private View view; + private JMenuItem undoMenuItem; + private JMenuItem redoMenuItem; + + public UndoMenuListener(View view, JMenuItem undoMenuItem, JMenuItem redoMenuItem){ + this.view = view; + this.undoMenuItem = undoMenuItem; + this.redoMenuItem = redoMenuItem; + } + + @Override + public void menuSelected(MenuEvent e) { + boolean canUndo = view.canUndo(); + boolean canRedo = view.canRedo(); + if (canUndo){ + undoMenuItem.setEnabled(true); + } else { + undoMenuItem.setEnabled(false); + } + + if (canRedo){ + redoMenuItem.setEnabled(true); + } else { + redoMenuItem.setEnabled(false); + } + } + + @Override + public void menuDeselected(MenuEvent e) { + + } + + @Override + public void menuCanceled(MenuEvent e) { + + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task32/task3209/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..24cebe9 --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task32/task3209/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,115 @@ +taskKey="com.javarush.task.task32.task3209.big24" + +HTML Editor (24) + +Твой html редактор готов! +Ты научился: +- Создавать приложения с графическим интерфейсом. +- Работать с диалоговыми окнами. +- Пользоваться классами из библиотеки Swing. +- Реализовывать взаимодействие компонентов программы с помощью событий, слушателей, +действий. +- Усилил свои знания в области MVC. + +Что можно улучшить в разработанном редакторе: +- Добавить панель инструментов, повторяющую функционал меню. +- Добавить подсветку html тегов на второй вкладке. +- Добавить возможность загрузки документа из Интернет. +- Расширить возможности редактора (вставка картинки, ссылки и т.д.) + +Поздравляю, так держать! + + +Требования: +1. html редактор готов! + + +HTML Editor (23) + +23.1. Напишем метод для сохранения открытого файла saveDocument(). Метод должен +работать также, как saveDocumentAs(), но не запрашивать файл у пользователя, а +использовать currentFile. Если currentFile равен null, то вызывать метод saveDocumentAs(). +23.2. Пришло время реализовать метод openDocument(). Метод должен работать +аналогично методу saveDocumentAs(), в той части, которая отвечает за выбор файла. +Подсказка: Обрати внимание на имя метода для показа диалогового окна. +Когда файл выбран, необходимо: +23.2.1. Установить новое значение currentFile. +23.2.2. Сбросить документ. +23.2.3. Установить имя файла в заголовок у представления. +23.2.4. Создать FileReader, используя currentFile. +23.2.5. Вычитать данные из FileReader-а в документ document с помощью объекта класса +HTMLEditorKit. +23.2.6. Сбросить правки (вызвать метод resetUndo представления). +23.2.7. Если возникнут исключения - залогируй их и не пробрасывай наружу. +Проверь работу пунктов меню Сохранить и Открыть. + + + +HTML Editor (22) + +Реализуем в контроллере метод для сохранения файла под новым именем saveDocumentAs(). +Реализация должна: +22.1. Переключать представление на html вкладку. +22.2. Создавать новый объект для выбора файла JFileChooser. +22.3. Устанавливать ему в качестве фильтра объект HTMLFileFilter. +22.4. Показывать диалоговое окно "Save File" для выбора файла. +22.5. Если пользователь подтвердит выбор файла: +22.5.1. Сохранять выбранный файл в поле currentFile. +22.5.2. Устанавливать имя файла в качестве заголовка окна представления. +22.5.3. Создавать FileWriter на базе currentFile. +22.5.4. Переписывать данные из документа document в объекта FileWriter-а аналогично тому, +как мы это делали в методе getPlainText(). +22.6. Метод не должен кидать исключения. +Проверь работу пункта меню Сохранить как... + + + +HTML Editor (21) + +Для открытия или сохранения файла мы будем использовать JFileChooser из библиотеки swing. +Объекты этого типа поддерживают фильтры, унаследованные от FileFilter. Сейчас мы напишем +свой фильтр: +21.1. Создай публичный класс HTMLFileFilter унаследованный от FileFilter. +21.2. Мы хотим, чтобы окно выбора файла отображало только html/htm файлы или папки. +Переопредели метод accept(File file), чтобы он возвращал true, если переданный файл +директория или содержит в конце имени ".html" или ".htm" без учета регистра. +21.3. Чтобы в окне выбора файла в описании доступных типов файлов отображался текст +"HTML и HTM файлы" переопредели соответствующим образом метод getDescription(). + + + +HTML Editor (20) + +20.1. Реализуй метод создания нового документа createNewDocument() в контроллере. Он +должен: +20.1.1. Выбирать html вкладку у представления. +20.1.2. Сбрасывать текущий документ. +20.1.3. Устанавливать новый заголовок окна, например: "HTML редактор". Воспользуйся +методом setTitle(), который унаследован в нашем представлении. +20.1.4. Сбрасывать правки в Undo менеджере. Используй метод resetUndo представления. +20.1.5. Обнулить переменную currentFile. +20.2. Реализуй метод инициализации init() контроллера. Он должен просто вызывать метод +создания нового документа. +Проверь работу пункта меню Новый. + + + +HTML Editor (19) + +Реализуем метод actionPerformed(ActionEvent actionEvent) у представления, этот метод +наследуется от интерфейса ActionListener и будет вызваться при выборе пунктов меню, у +которых наше представление указано в виде слушателя событий. +19.1. Получи из события команду с помощью метода getActionCommand(). Это будет +обычная строка. По этой строке ты можешь понять какой пункт меню создал данное +событие. +19.2. Если это команда "Новый", вызови у контроллера метод createNewDocument(). В этом +пункте и далее, если необходимого метода в контроллере еще нет - создай заглушки. +19.3. Если это команда "Открыть", вызови метод openDocument(). +19.4. Если "Сохранить", то вызови saveDocument(). +19.5. Если "Сохранить как..." - saveDocumentAs(). +19.6. Если "Выход" - exit(). +19.7. Если "О программе", то вызови метод showAbout() у представления. +Проверь, что заработали пункты меню Выход и О программе. + + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Controller.java b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Controller.java new file mode 100644 index 0000000..7efa1db --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Controller.java @@ -0,0 +1,71 @@ +package com.javarush.task.task35.task3513; + +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; + +/** + * Created by ArchMage on 11.04.17. + */ +public class Controller extends KeyAdapter { + private Model model; + private View view; + private final static int WINNING_TILE = 2048; + + public Controller(Model model) { + this.model = model; + view = new View(this); + } + + public void resetGame(){ + view.isGameLost = false; + view.isGameWon = false; + model.score = 0; + model.resetGameTiles(); + } + + public View getView() { + return view; + } + + public Tile[][] getGameTiles(){ + return model.getGameTiles(); + } + + public int getScore(){ + return model.score; + } + + @Override + public void keyPressed(KeyEvent e) { + int code = e.getKeyCode(); + if (code == 27) { + resetGame(); + } else { + if (!model.canMove()) { + view.isGameLost = true; + } else{ + if (!view.isGameLost && !view.isGameWon) { + if (e.getKeyCode() == KeyEvent.VK_LEFT) { + model.left(); + } else if (e.getKeyCode() == KeyEvent.VK_UP) { + model.up(); + }else if (e.getKeyCode() == KeyEvent.VK_RIGHT) { + model.right(); + }else if (e.getKeyCode() == KeyEvent.VK_DOWN) { + model.down(); + }else if (e.getKeyCode() == KeyEvent.VK_Z){ + model.rollback(); + }else if (e.getKeyCode() == KeyEvent.VK_R){ + model.randomMove(); + }else if (e.getKeyCode() == KeyEvent.VK_A){ + model.autoMove(); + } + + if (model.maxTile == WINNING_TILE) { view.isGameWon = true; } + } + } + } + view.repaint(); + + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Main.java b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Main.java new file mode 100644 index 0000000..52be888 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Main.java @@ -0,0 +1,21 @@ +package com.javarush.task.task35.task3513; + +import javax.swing.*; + +/** + * Created by ArchMage on 11.04.17. + */ +public class Main { + public static void main(String[] args){ + Model gameModel = new Model(); + Controller controller = new Controller(gameModel); + JFrame game = new JFrame(); + game.setTitle("2048"); + game.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + game.setSize(450, 500); + game.setResizable(false); + game.add(controller.getView()); + game.setLocationRelativeTo(null); + game.setVisible(true); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Model.java b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Model.java new file mode 100644 index 0000000..ef4dc31 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Model.java @@ -0,0 +1,355 @@ +package com.javarush.task.task35.task3513; + +import java.util.*; + +/** + * Created by ArchMage on 11.04.17. + */ +public class Model { + private static final int FIELD_WIDTH = 4; + private Tile[][] gameTiles; + protected int score; + protected int maxTile; + private Stack previousStates = new Stack(); + private Stack previousScores = new Stack(); + private boolean isSaveNeeded = true; + + public Model(){ + resetGameTiles(); + } + + private void addTile(){ + List emptyList = getEmptyTiles(); + if (emptyList != null && emptyList.size() != 0) { + Tile tile = emptyList.get((int) (Math.random() * emptyList.size())); + int tileWeight = Math.random() < 0.9 ? 2 : 4; + tile.value = tileWeight; + } + } + + private void saveState(Tile[][] tiles){ + Tile[][] tempTile = new Tile[FIELD_WIDTH][FIELD_WIDTH]; + for (int i = 0; i < FIELD_WIDTH; i++){ + for (int j = 0; j < FIELD_WIDTH; j++) { + tempTile[i][j] = new Tile(tiles[i][j].value); + } + } + previousStates.push(tempTile); + previousScores.push(score); + isSaveNeeded = false; + } + + public void rollback(){ + if (!previousStates.isEmpty() && !previousScores.isEmpty()) { + gameTiles = (Tile[][]) previousStates.pop(); + score = (int) previousScores.pop(); + } + } + + protected void resetGameTiles(){ + gameTiles = new Tile[FIELD_WIDTH][FIELD_WIDTH]; + for (int i = 0; i < FIELD_WIDTH; i++){ + for (int j = 0; j < FIELD_WIDTH; j++){ + gameTiles[i][j] = new Tile(); + } + } + addTile(); + addTile(); + maxTile = 2; + score = 0; + } + + private List getEmptyTiles(){ + ArrayList emptyTilesList = new ArrayList(); + for (int i = 0; i < FIELD_WIDTH; i++){ + for (int j = 0; j < FIELD_WIDTH; j++){ + if (gameTiles[i][j].isEmpty()) { + emptyTilesList.add(gameTiles[i][j]); + } + } + } + return emptyTilesList; + } + + /*private boolean compressTiles(Tile[] tiles){ + boolean isChanged = true; + for (int i = 0; i < tiles.length; i++){ + if (tiles[i].value == 0) { + boolean isAllZero = false; + for (int j = 1; j <= tiles.length - i; j++) { + try { + if (tiles[i+j].value != 0) { isAllZero = false; } + tiles[i + j - 1].value = tiles[i + j].value; + + } catch (Exception e) { + tiles[i + j - 1].value = 0; + + } + } + if (tiles[i].value == 0 && !isAllZero) { i--; } + } + } + + return false; + }*/ + + private boolean compressTiles(Tile[] tiles){ + int counter = 0; + boolean isChanged = false; + int values[] = new int[tiles.length]; + for (int i = 0; i < values.length; i++){ + values[i] = 0; + } + + for (int i = 0; i < tiles.length; i++){ + if (tiles[i].value != 0) { + values[counter] = tiles[i].value; + counter++; + } + } + + for (int i = 0; i < tiles.length; i++){ + if (values[i] != tiles[i].value) { isChanged = true; } + tiles[i].value = values[i]; + } + + return isChanged; + + } + + private boolean mergeTiles(Tile[] tiles){ + boolean isChanged = false; + for (int i = 0; i < tiles.length - 1; i++){ + if (tiles[i].value == tiles[i+1].value && tiles[i].value != 0) { + tiles[i].value = tiles[i].value * 2; + score = score + tiles[i].value; + if (tiles[i].value > maxTile) { maxTile = tiles[i].value; } + for (int j = 2; j <= tiles.length - i; j++){ + try { + tiles[i + j - 1 ].value = tiles[i + j].value; + } catch (Exception e){ + tiles[i + j - 1].value = 0; + isChanged = true; + } + } + } + } + return isChanged; + } + + public void left(){ + if (isSaveNeeded) { saveState(gameTiles); } + boolean isChanged = false; + for (int i = 0; i < FIELD_WIDTH; i++){ + if (compressTiles(gameTiles[i])) { isChanged = true; } + if (mergeTiles(gameTiles[i])) { isChanged = true; } + } + if (isChanged) {addTile(); } + isSaveNeeded = true; + } + + public void up(){ + saveState(gameTiles); + rotate(gameTiles); + rotate(gameTiles); + rotate(gameTiles); + left(); + rotate(gameTiles); + } + + public void right(){ + saveState(gameTiles); + rotate(gameTiles); + rotate(gameTiles); + left(); + rotate(gameTiles); + rotate(gameTiles); + } + + public void down(){ + saveState(gameTiles); + rotate(gameTiles); + left(); + rotate(gameTiles); + rotate(gameTiles); + rotate(gameTiles); + } + + private void rotate(Tile[][] arrayGameTiles){ + int[][] values = new int[FIELD_WIDTH][FIELD_WIDTH]; + for (int i = 0; i < FIELD_WIDTH; i++){ + for (int j = 0; j < FIELD_WIDTH; j++){ + values[i][j] = arrayGameTiles[i][j].value; + } + } + + for (int i = 0; i < FIELD_WIDTH; i++){ + for (int j = 0; j < FIELD_WIDTH; j++){ + arrayGameTiles[j][FIELD_WIDTH - i - 1].value = values[i][j]; + } + } + } + + public Tile[][] getGameTiles() { + return gameTiles; + } + + public boolean canMove(){ + Tile[][] tempArray = new Tile[FIELD_WIDTH][FIELD_WIDTH]; + for (int i = 0; i < FIELD_WIDTH; i++){ + for (int j = 0; j < FIELD_WIDTH; j++){ + tempArray[i][j] = new Tile(gameTiles[i][j].value); + } + } + + + for (int i = 0; i < 4; i++) { + if (canMoveLeft(tempArray)) { + return true; + } + rotate(tempArray); + } + return false; + } + + private boolean canMoveLeft(Tile[][] arrayGameTiles){ + for (int i = 0; i < FIELD_WIDTH; i++){ + if (testCompressTiles(arrayGameTiles[i])) { return true; } + if (testMergeTiles(arrayGameTiles[i])) { return true; } + } + return false; + } + + // Вынесем тестовые методы сюда. Лучше, конечно, добавить возможность тестового вызова в аналогичные "настоящие" методы, + // но непонятно, как на смену сигнатуры методов отреагирует валидатор + + private boolean testCompressTiles(Tile[] tiles){ + int counter = 0; + int values[] = new int[tiles.length]; + for (int i = 0; i < values.length; i++){ + values[i] = 0; + } + + for (int i = 0; i < tiles.length; i++){ + if (tiles[i].value != 0) { + values[counter] = tiles[i].value; + counter++; + } + } + + for (int i = 0; i < tiles.length; i++){ + if (values[i] != tiles[i].value) { return true; } + tiles[i].value = values[i]; + } + + return false; + + } + + private boolean testMergeTiles(Tile[] tiles){ + for (int i = 0; i < tiles.length - 1; i++){ + if (tiles[i].value == tiles[i+1].value && tiles[i].value != 0) { + tiles[i].value = tiles[i].value * 2; + // В настоящих методах, тут шло изменение счета и максимальной плашки, но в тестовом методе, + // их затрагивать нельзя + + for (int j = 2; j <= tiles.length - i; j++){ + try { + tiles[i + j - 1 ].value = tiles[i + j].value; + } catch (Exception e){ + tiles[i + j - 1].value = 0; + return true; + } + } + } + } + return false; + } + + public void randomMove(){ + int n = ((int) (Math.random() * 100)) % 4; + switch (n){ + case 0: + left(); + break; + case 1: + right(); + break; + case 2: + up(); + break; + case 3: + down(); + break; + } + } + + private boolean hasBoardChanged(){ + Tile[][] prev = (Tile[][]) previousStates.peek(); + int currTile = 0; + int prevTile = 0; + for (int i = 0; i < FIELD_WIDTH; i++) { + for (int j = 0; j < FIELD_WIDTH; j++) { + currTile += gameTiles[i][j].value; + prevTile += prev[i][j].value; + } + } + + return currTile != prevTile; + } + + public MoveEfficiency getMoveEfficiency(Move move){ + MoveEfficiency movEff = null; + move.move(); + + if (!hasBoardChanged()) { + movEff = new MoveEfficiency(-1 ,0 ,move); + } else { + movEff = new MoveEfficiency(getEmptyTiles().size() ,score ,move); + } + rollback(); + return movEff; + } + + public void autoMove(){ + PriorityQueue queue = new PriorityQueue(4, Collections.reverseOrder()); + queue.add(getMoveEfficiency(this::randomMove)); + queue.offer(getMoveEfficiency(this::right)); + queue.offer(getMoveEfficiency(this::up)); + queue.offer(getMoveEfficiency(this::down)); + MoveEfficiency efficientMove = (MoveEfficiency) queue.poll(); + efficientMove.getMove().move(); + } + + private class MoveLeft implements Move{ + + @Override + public void move() { + Model.this.left(); + } + } + + private class MoveUp implements Move{ + + @Override + public void move() { + Model.this.up(); + } + } + + private class MoveRight implements Move{ + + @Override + public void move() { + Model.this.right(); + } + } + + private class MoveDown implements Move{ + + @Override + public void move() { + Model.this.down(); + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Move.java b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Move.java new file mode 100644 index 0000000..d2ce60a --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Move.java @@ -0,0 +1,9 @@ +package com.javarush.task.task35.task3513; + +/** + * Created by ArchMage on 12.04.17. + */ +@FunctionalInterface +public interface Move { + void move(); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task35/task3513/MoveEfficiency.java b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/MoveEfficiency.java new file mode 100644 index 0000000..ba1cbc4 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/MoveEfficiency.java @@ -0,0 +1,27 @@ +package com.javarush.task.task35.task3513; + +/** + * Created by ArchMage on 12.04.17. + */ +public class MoveEfficiency implements Comparable { + private int numberOfEmptyTiles; + private int score; + private Move move; + + public MoveEfficiency(int numberOfEmptyTiles, int score, Move move) { + this.numberOfEmptyTiles = numberOfEmptyTiles; + this.score = score; + this.move = move; + } + + public Move getMove() { + return move; + } + + @Override + public int compareTo(MoveEfficiency o) { + if (numberOfEmptyTiles != o.numberOfEmptyTiles) { + return Integer.compare(numberOfEmptyTiles, o.numberOfEmptyTiles); + } else return Integer.compare(score, o.score); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Tile.java b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Tile.java new file mode 100644 index 0000000..e944b8f --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/Tile.java @@ -0,0 +1,58 @@ +package com.javarush.task.task35.task3513; + +import java.awt.*; + +/** + * Created by ArchMage on 11.04.17. + */ +public class Tile { + int value; + + public Tile(int value) { + this.value = value; + } + + public Tile() { + } + + public boolean isEmpty(){ + if (value == 0) { return true; } + else { return false; } + } + + public Color getFontColor(){ + if (value < 16) { return new Color(0x776e65); } + else { return new Color(0xf9f6f2); } + } + + public Color getTileColor(){ + switch (value) { + case 0: return new Color(0xcdc1b4); + + case 2: return new Color(0xeee4da); + + case 4: return new Color(0xede0c8); + + case 8: return new Color(0xf2b179); + + case 16: return new Color(0xf59563); + + case 32: return new Color(0xf67c5f); + + case 64: return new Color(0xf65e3b); + + case 128: return new Color(0xedcf72); + + case 256: return new Color(0xedcc61); + + case 512: return new Color(0xedc850); + + case 1024: return new Color(0xedc53f); + + case 2048: return new Color(0xedc22e); + + default: return new Color(0xff0000); + + } + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task35/task3513/View.java b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/View.java new file mode 100644 index 0000000..0bd0ec2 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/View.java @@ -0,0 +1,69 @@ +package com.javarush.task.task35.task3513; + +import javax.swing.*; +import java.awt.*; + +public class View extends JPanel { + private static final Color BG_COLOR = new Color(0xbbada0); + private static final String FONT_NAME = "Arial"; + private static final int TILE_SIZE = 96; + private static final int TILE_MARGIN = 12; + + private Controller controller; + + boolean isGameWon = false; + boolean isGameLost = false; + + public View(Controller controller) { + setFocusable(true); + this.controller = controller; + addKeyListener(controller); + } + + @Override + public void paint(Graphics g) { + super.paint(g); + g.setColor(BG_COLOR); + g.fillRect(0, 0, this.getSize().width, this.getSize().height); + for (int x = 0; x < 4; x++) { + for (int y = 0; y < 4; y++) { + drawTile(g, controller.getGameTiles()[y][x], x, y); + } + } + + g.drawString("Score: " + controller.getScore(), 140, 465); + + if (isGameWon) { + JOptionPane.showMessageDialog(this, "You've won!"); + } else if(isGameLost) { + JOptionPane.showMessageDialog(this, "You've lost :("); + } + } + + private void drawTile(Graphics g2, Tile tile, int x, int y) { + Graphics2D g = ((Graphics2D) g2); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + int value = tile.value; + int xOffset = offsetCoors(x); + int yOffset = offsetCoors(y); + g.setColor(tile.getTileColor()); + g.fillRoundRect(xOffset, yOffset, TILE_SIZE, TILE_SIZE , 8, 8); + g.setColor(tile.getFontColor()); + final int size = value < 100 ? 36 : value < 1000 ? 32 : 24; + final Font font = new Font(FONT_NAME, Font.BOLD, size); + g.setFont(font); + + String s = String.valueOf(value); + final FontMetrics fm = getFontMetrics(font); + + final int w = fm.stringWidth(s); + final int h = -(int) fm.getLineMetrics(s, g).getBaselineOffsets()[2]; + + if (value != 0) + g.drawString(s, xOffset + (TILE_SIZE - w) / 2, yOffset + TILE_SIZE - (TILE_SIZE - h) / 2 - 2); + } + + private static int offsetCoors(int arg) { + return arg * (TILE_MARGIN + TILE_SIZE) + TILE_MARGIN; + } +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task35/task3513/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..c3d151a --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task35/task3513/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,146 @@ +taskKey="com.javarush.task.task35.task3513.big16" + +2048 (16) + +Осталось совсем немного! У нас есть способ вычислить эффективность любого хода, а также мы можем их сравнивать +между собой. + +Давай реализуем метод autoMove в классе Model, который будет выбирать лучший из возможных ходов и выполнять его. + +Сделаем так: +1) Создадим локальную PriorityQueue с параметром Collections.reverseOrder() (для того, +чтобы вверху очереди всегда был максимальный элемент) и размером равным четырем. +2) Заполним PriorityQueue четырьмя объектами типа MoveEfficiency (по одному на каждый вариант хода). +3) Возьмем верхний элемент и выполним ход связанный с ним. + +После реализации метода autoMove добавим его вызов в метод keyPressed класса Controller +по нажатию на клавишу A (код - KeyEvent.VK_A). + +P.S. В качестве факультативного задания можешь почитать про указатели на методы и попробовать передать +аргумент в метод getMoveEfficiency используя оператор "::". Для метода left должно получиться +getMoveEfficiency(this::left). Альтернативно можешь использовать внутренний анонимный класс. + + +Требования: +1. В методе autoMove должен быть создан объект типа PriorityQueue. +2. В методе autoMove в PriorityQueue должно быть добавлено 4 объекта типа MoveEfficiency с помощью метода offer (по одному на каждый вариант хода). +3. Метод keyPressed класса Controller должен вызывать метод autoMove у модели в случае, если была нажата клавиша с кодом KeyEvent.VK_A. +4. В методе autoMove должен быть выполнен метод move связанный с объектом MoveEfficiency полученном с помощью метода peek или poll. + + +2048 (15) + +Для того, чтобы эффективности различных ходов можно было сравнивать, необходимо реализовать в классе +MoveEfficiency поддержку интерфейса Comparable. + +В методе compareTo первым делом сравни количество пустых плиток (numberOfEmptyTiles), потом счет (score), +если количество пустых плиток равное. Если и счет окажется равным, будем считать эффективность ходов +равной и вернем ноль. + +Далее перейдем в класс Model и реализуем два метода: +1) boolean hasBoardChanged - будет возвращать true, в случае, если вес плиток в массиве gameTiles +отличается от веса плиток в верхнем массиве стека previousStates. Обрати внимание на то, что мы +не должны удалять из стека верхний элемент, используй метод peek. +2) MoveEfficiency getMoveEfficiency(Move move) - принимает один параметр типа move, и возвращает +объект типа MoveEfficiency описывающий эффективность переданного хода. Несколько советов: +а) не забудь вызывать метод rollback, чтобы восстановить корректное игровое состояние; +б) в случае, если ход не меняет состояние игрового поля, количество пустых плиток и счет у объекта MoveEfficiency +сделай равными -1 и 0 соответственно; +в) выполнить ход можно вызвав метод move на объекте полученном в качестве параметра. + + + +2048 (14) + +Случайный ход конечно неплох, но намного круче реализовать возможность умного хода. В дебри нейронных сетей +мы заходить не будем, для начала сконцентрируемся на достаточно простой идее. + +Очевидно, хороший ход должен в итоге приближать нас к победе, а именно к получению плитки 2048. +Предлагаю рассмотреть такой вариант сравнения эффективности хода: +1) Первый ход является лучше второго, если после его совершения на поле находится больше пустых плиток, +чем в результате второго хода. +2) Первый ход является лучше второго, если общий счет после его совершения больше, чем счет +полученный в результате второго хода. + +Для того, чтобы реализовать такое сравнение, мы можем совершить ход, оценить его эффективность и потом +отменить совершенный ход, чтобы вернуть игру в начальное состояние. Применив эту последовательность действий +ко всем четырем вариантам хода, сможем выбрать наиболее эффективный ход и выполнить его. + +Концептуально, нам понадобятся два класса, один будет описывать ход, а другой эффективность хода. + +Создай интерфейс Move с одним void методом move. Отметь интерфейс аннотацией @FunctionalInterface, которая +будет сигнализировать о том что в этом интерфейсе будет только один абстрактный метод. + +Создай класс MoveEfficiency, описывающий эффективность хода. В нем нам понадобятся приватные поля +numberOfEmptyTiles и score типа int, а также приватное поле поле move типа Move. +В классе MoveEfficiency необходим конструктор с тремя параметрами (int numberOfEmptyTiles, int score, Move move) +для инициализации полей класса и геттер для поля move. + + + +2048 (13) + +Твой прогресс впечатляет! Для разнообразия, предлагаю дать игре возможность самостоятельно +выбирать следующий ход. + +Начнем с простого, реализуем метод randomMove в классе Model, который будет вызывать один из методов движения +случайным образом. Можешь реализовать это вычислив целочисленное n = ((int) (Math.random() * 100)) % 4. +Это число будет содержать целое псевдослучайное число в диапазоне [0..3], по каждому из которых можешь вызывать +один из методов left, right, up, down. + +Не забудь добавить в метод keyPressed класса Controller вызов метода randomMove по нажатию на клавишу R +(код - KeyEvent.VK_R). + +P.S. Проверку корректности работы метода randomMove оставляю полностью под твою ответственность, +проверю только наличие вызова метода Math.random(). + + + +2048 (12) + +Ну что, попробуем наш алгоритм в действии? Осталось добавить сохранение игрового состояния в начало каждого +метода движения, а также еще один кейс для обработки клавиши, которой будем выполнять отмену последнего хода. + +При сохранении текущего состояния в стек, обрати внимание на то, чтобы всегда сохранялось актуальное состояние +и только однажды. Если ты послушал мой совет и реализовал методы right, up, down с помощью поворотов и вызова +метода left, можешь использовать следующий подход: +1) В самом начале методов right, up, down вызываем метод saveState с gameTiles в качестве параметра. +2) В методе left организуем проверку того, вызывался ли уже метод saveState. За это у нас отвечает +флаг isSaveNeeded, соответственно, если он равен true, выполняем сохранение. После выполнения +сдвига влево устанавливаем флаг isSaveNeeded равным true. + +Также добавим в метод keyPressed класса Controller вызов метода rollback по нажатию на клавишу Z (код - KeyEvent.VK_Z). + + + +2048 (11) + +Отличная работа! На этом этапе у нас уже есть полнофункциональное приложение, но ведь нет предела совершенству, +давай еще поработаем. + +Если ты успел какое-то время поиграть в 2048, то заметил, что порой очень хочется иметь возможность отменить +последний ход. + +Давай создадим в классе Model два стека, в одном будем хранить предыдущие состояния игрового поля, а в другом +предыдущие счета. Назовем их previousStates и previousScores. Инициализировать можешь прямо в строке объявления +или в конструкторе. Используй стандартную реализацию стека (java.util.Stack). + +Добавим boolean поле isSaveNeeded = true, оно нам понадобится в будущем. + +Хранилище состояний у нас есть, теперь реализуем два метода для работы с ними. +1. Приватный метод saveState с одним параметром типа Tile[][] будет сохранять текущее +игровое состояние и счет в стеки с помощью метода push и устанавливать флаг isSaveNeeded равным false. +2. Публичный метод rollback будет устанавливать текущее игровое состояние равным последнему находящемуся +в стеках с помощью метода pop. + +Обрати внимание на то, что при сохранении массива gameTiles необходимо создать новый массив и заполнить его +новыми объектами типа Tile перед сохранением в стек. + +В методе rollback достаточно просто выполнить присваивание (gameTiles = previousStates.pop()) и то же для счета, +нет необходимости в глубоком копировании. + +Перед восстановлением игрового состояния с помощью метода rollback не забудь проверить что стеки не пусты, +чтобы избежать возникновения исключения EmptyStackException. + + + diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/Solution.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/Solution.java new file mode 100644 index 0000000..76334d6 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/Solution.java @@ -0,0 +1,30 @@ +package com.javarush.task.task36.task3608; + +import com.javarush.task.task36.task3608.controller.Controller; + +//import com.javarush.task.task36.task3608.model.FakeModel; +import com.javarush.task.task36.task3608.model.MainModel; +import com.javarush.task.task36.task3608.model.Model; +import com.javarush.task.task36.task3608.view.EditUserView; +import com.javarush.task.task36.task3608.view.UsersView; + +public class Solution { + public static void main(String[] args) { + Model model = new MainModel(); + UsersView usersView = new UsersView(); + Controller controller = new Controller(); + EditUserView editUserView = new EditUserView(); + + usersView.setController(controller); + editUserView.setController(controller); + controller.setModel(model); + controller.setUsersView(usersView); + + usersView.fireEventShowAllUsers(); + usersView.fireEventOpenUserEditForm(126L); + editUserView.fireEventUserDeleted(124L); + editUserView.fireEventUserChanged("Ivanov", 123l, 3); + + usersView.fireEventShowDeletedUsers(); + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/Util.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/Util.java new file mode 100644 index 0000000..11e5239 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/Util.java @@ -0,0 +1,17 @@ +package com.javarush.task.task36.task3608; + +import com.javarush.task.task36.task3608.bean.User; + +public final class Util { + public static final String DELETED_MARKER = " (deleted)"; + + public static boolean isUserDeleted(User user) { + return user.getName().endsWith(DELETED_MARKER); + } + + public static void markDeleted(User user) { + if (User.NULL_USER != user && !Util.isUserDeleted(user)) { + user.setName(user.getName() + DELETED_MARKER); + } + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/bean/User.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/bean/User.java new file mode 100644 index 0000000..6c70185 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/bean/User.java @@ -0,0 +1,69 @@ +package com.javarush.task.task36.task3608.bean; + +public class User implements Cloneable { + private String name; + private final long id; + private int level; + + public static final User NULL_USER = new User(); + + public User(String name, long id, int level) { + this.name = name; + this.id = id; + this.level = level; + } + + public User() { + this("", 0, 0); + } + + + //methods with logic + public boolean isNew() { + return id == 0; + } + + public User clone() { + try { + return (User) super.clone(); + } catch (CloneNotSupportedException ignored) { + return NULL_USER; + } + } + + public User clone(long newId) { + if (this == NULL_USER) return NULL_USER; + + return new User(name, newId, level); + } + + ///// getters and setters + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public long getId() { + return id; + } + + public int getLevel() { + return level; + } + + public void setLevel(int level) { + this.level = level; + } + + @Override + public String toString() { + return "User{" + + "name='" + name + '\'' + + ", id=" + id + + ", level=" + level + + '}'; + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/controller/Controller.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/controller/Controller.java new file mode 100644 index 0000000..76c448f --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/controller/Controller.java @@ -0,0 +1,53 @@ +package com.javarush.task.task36.task3608.controller; + +import com.javarush.task.task36.task3608.model.Model; +import com.javarush.task.task36.task3608.view.EditUserView; +import com.javarush.task.task36.task3608.view.UsersView; + +/** + * Created by PAKOT on 11.03.2017. + */ +public class Controller { + private Model model; + private UsersView usersView = new UsersView(); + private EditUserView editUserView = new EditUserView(); + + public void setModel(Model model) { + this.model = model; + } + + public void onShowAllUsers(){ + model.loadUsers(); + usersView.refresh(model.getModelData()); + } + + public void onShowAllDeletedUsers() { + model.loadDeletedUsers(); + usersView.refresh(model.getModelData()); + + } + + public void setUsersView(UsersView usersView) { + this.usersView = usersView; + + } + + public void setEditUserView(EditUserView editUserView){ + this.editUserView = editUserView; + } + + public void onOpenUserEditForm(long userId) { + model.loadUserById(userId); + editUserView.refresh(model.getModelData()); + } + + public void onUserDelete(long id){ + model.deleteUserById(id); + usersView.refresh(model.getModelData()); + } + + public void onUserChange(String name, long id, int level){ + model.changeUserData(name, id, level); + usersView.refresh(model.getModelData()); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/dao/UserDao.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/dao/UserDao.java new file mode 100644 index 0000000..1cf69d7 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/dao/UserDao.java @@ -0,0 +1,82 @@ +package com.javarush.task.task36.task3608.dao; + +import com.javarush.task.task36.task3608.bean.User; +import com.javarush.task.task36.task3608.dao.mock.DataSource; + +import java.util.ArrayList; +import java.util.List; + +public class UserDao { + private DataSource dataSource = DataSource.getInstance(); + + public User getUserById(long id) { + List users = dataSource.getUsers(); + for (User user : users) { + if (user.getId() == id) { + return user.clone(); + } + } + return User.NULL_USER; + } + + public List getUsersByName(String name) { + if (name == null || name.trim().isEmpty()) throw new IllegalArgumentException(); + + List users = dataSource.getUsers(); + List result = new ArrayList<>(); + for (User user : users) { + if (name.equals(user.getName())) { + addUserToResult(result, user); + } + } + return result; + } + + public List getAllUsers() { + List users = dataSource.getUsers(); + List result = new ArrayList<>(); + for (User user : users) { + addUserToResult(result, user); + } + return result; + } + + public List getUsersByLevel(int level) { + if (level < 1) throw new IllegalArgumentException(); + + List users = dataSource.getUsers(); + List result = new ArrayList<>(); + + for (User user : users) { + if (level == user.getLevel()) { + addUserToResult(result, user); + } + } + return result; + } + + public void addUserToResult(List result, User user) { + User clone = user.clone(); + + //skip bad users + if (clone != User.NULL_USER) { + result.add(clone); + } + } + + public User createOrUpdate(User user) { + return dataSource.createOrUpdate(user); + } + + public User getUsersById(long userId) { + if (userId < 1) throw new IllegalArgumentException(); + + List users = dataSource.getUsers(); + for (User user : users) { + if (userId == user.getId()) { + return user; + } + } + return User.NULL_USER; + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/dao/mock/DataSource.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/dao/mock/DataSource.java new file mode 100644 index 0000000..8d8189a --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/dao/mock/DataSource.java @@ -0,0 +1,59 @@ +package com.javarush.task.task36.task3608.dao.mock; + +import com.javarush.task.task36.task3608.bean.User; + +import java.util.LinkedList; +import java.util.List; + +public class DataSource { + private static DataSource ourInstance = new DataSource(); + + public static DataSource getInstance() { + return ourInstance; + } + + private DataSource() { + } + + private List users = new LinkedList() {{ + add(new User("Ivanov", 123l, 1)); + add(new User("Petrov", 124l, 2)); + add(new User("Petrov", 125l, 1)); + add(new User("Sidorov", 126l, 2)); + }}; + + private long maxUserId = 126l; + + public List getUsers() { + return users; + } + + public User createOrUpdate(User newUser) { + if (newUser == User.NULL_USER) + return User.NULL_USER; + + //new User + if (newUser.getId() == 0) + return createNewUser(newUser); + else + return updateUser(newUser); + } + + private User createNewUser(User newUser) { + User clone = newUser.clone(++maxUserId); + users.add(clone); + return clone; + } + + private User updateUser(User newUser) { + for (User user : users) { + if (user.getId() == newUser.getId()) { + user.setName(newUser.getName()); + user.setLevel(newUser.getLevel()); + return user; + } + } + //if we didn't find such a user + return User.NULL_USER; + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/FakeModel.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/FakeModel.java new file mode 100644 index 0000000..24fc922 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/FakeModel.java @@ -0,0 +1,52 @@ +package com.javarush.task.task36.task3608.model; + +import com.javarush.task.task36.task3608.bean.User; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by PAKOT on 11.03.2017. + */ +public class FakeModel implements Model { + private ModelData modelData = new ModelData(); + + @Override + public ModelData getModelData() { + return modelData; + } + + @Override + public void loadUsers() { + List testUsers = new ArrayList(); + User user1 = new User("Amigo", 1, 24); + User user2 = new User("Zajaz", 2, 27); + User user3 = new User("Newbie", 3, 7); + User user4 = new User("Jaja", 4, 14); + testUsers.add(user1); + testUsers.add(user2); + testUsers.add(user3); + testUsers.add(user4); + modelData.setUsers(testUsers); + } + + @Override + public void loadDeletedUsers() { + throw new UnsupportedOperationException(); + } + + @Override + public void loadUserById(long userId) { + throw new UnsupportedOperationException(); + } + + @Override + public void deleteUserById(long id) { + throw new UnsupportedOperationException(); + } + + @Override + public void changeUserData(String name, long id, int level) { + throw new UnsupportedOperationException(); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/MainModel.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/MainModel.java new file mode 100644 index 0000000..e367995 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/MainModel.java @@ -0,0 +1,57 @@ +package com.javarush.task.task36.task3608.model; + +import com.javarush.task.task36.task3608.bean.User; + +import com.javarush.task.task36.task3608.model.service.UserService; +import com.javarush.task.task36.task3608.model.service.UserServiceImpl; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by PAKOT on 11.03.2017. + */ +public class MainModel implements Model { + private ModelData modelData = new ModelData(); + private UserService userService = new UserServiceImpl(); + + @Override + public ModelData getModelData() { + return modelData; + } + + @Override + public void loadUsers() { + //List list = userService.getUsersBetweenLevels(1, 100); + modelData.setUsers(getAllUsers()); + modelData.setDisplayDeletedUserList(false); + } + + public void loadDeletedUsers() { + //List users = userService.getAllDeletedUsers(); + modelData.setUsers(userService.getAllDeletedUsers()); + modelData.setDisplayDeletedUserList(true); + } + + public void loadUserById(long userId) { + User user = userService.getUsersById(userId); + modelData.setActiveUser(user); + } + + public void deleteUserById(long id){ + userService.deleteUser(id); + modelData.setDisplayDeletedUserList(false); + modelData.setUsers(getAllUsers()); + + + } + + public void changeUserData(String name, long id, int level){ + userService.createOrUpdateUser(name, id, level); + modelData.setUsers(getAllUsers()); + } + + private List getAllUsers(){ + return userService.filterOnlyActiveUsers(userService.getUsersBetweenLevels(1, 100)); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/Model.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/Model.java new file mode 100644 index 0000000..1117b31 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/Model.java @@ -0,0 +1,14 @@ +package com.javarush.task.task36.task3608.model; + +/** + * Created by PAKOT on 11.03.2017. + */ +public interface Model { + ModelData getModelData(); + + void loadUsers(); + void loadDeletedUsers(); + void loadUserById(long userId); + void deleteUserById(long id); + void changeUserData(String name, long id, int level); +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/ModelData.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/ModelData.java new file mode 100644 index 0000000..9013fb8 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/ModelData.java @@ -0,0 +1,40 @@ +package com.javarush.task.task36.task3608.model; + +import com.javarush.task.task36.task3608.bean.User; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by PAKOT on 11.03.2017. + */ +public class ModelData { + private List users; + private User activeUser; + private boolean displayDeletedUserList; + + public boolean isDisplayDeletedUserList() { + return displayDeletedUserList; + } + + public void setDisplayDeletedUserList(boolean displayDeletedUserList) { + this.displayDeletedUserList = displayDeletedUserList; + } + + public User getActiveUser() { + return activeUser; + } + + public void setActiveUser(User activeUser) { + this.activeUser = activeUser; + } + + public List getUsers() { + return users; + } + + public void setUsers(List users) { + this.users = users; + } + +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/service/UserService.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/service/UserService.java new file mode 100644 index 0000000..a78aa38 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/service/UserService.java @@ -0,0 +1,21 @@ +package com.javarush.task.task36.task3608.model.service; + +import com.javarush.task.task36.task3608.bean.User; + +import java.util.List; + +public interface UserService { + public User deleteUser(long id); + + public User createOrUpdateUser(String name, long id, int level); + + public List getUsersByName(String name); + + public List getAllDeletedUsers(); + + public List getUsersBetweenLevels(int fromLevel, int toLevel); + + List filterOnlyActiveUsers(List allUsers); + + User getUsersById(long userId); +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/service/UserServiceImpl.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/service/UserServiceImpl.java new file mode 100644 index 0000000..443a22c --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/model/service/UserServiceImpl.java @@ -0,0 +1,73 @@ +package com.javarush.task.task36.task3608.model.service; + +import com.javarush.task.task36.task3608.Util; +import com.javarush.task.task36.task3608.bean.User; +import com.javarush.task.task36.task3608.dao.UserDao; + +import java.util.ArrayList; +import java.util.List; + +public class UserServiceImpl implements UserService { + private UserDao userDao = new UserDao(); + + @Override + public User deleteUser(long id) { + User user = userDao.getUserById(id); + Util.markDeleted(user); + userDao.createOrUpdate(user); + + return user; + } + + @Override + public User createOrUpdateUser(String name, long id, int level) { + User user = new User(name, id, level); + return userDao.createOrUpdate(user); + } + + @Override + public List getUsersByName(String name) { + return userDao.getUsersByName(name); + } + + @Override + public List getAllDeletedUsers() { + List result = new ArrayList<>(); + for (User user : userDao.getAllUsers()) { + if (Util.isUserDeleted(user)) { + result.add(user); + } + } + + return result; + } + + @Override + public List getUsersBetweenLevels(int fromLevel, int toLevel) { + //it's better to get all users from DAO by one DB request, but we will use what we have + List result = new ArrayList<>(); + for (int i = fromLevel; i <= toLevel; i++) { + result.addAll(userDao.getUsersByLevel(i)); + } + + return result; + } + + @Override + public List filterOnlyActiveUsers(List allUsers) { + //will not change allUsers list, create new one instead of that + List result = new ArrayList<>(); + for (User user : allUsers) { + if (User.NULL_USER != user && !Util.isUserDeleted(user)) { + result.add(user); + } + } + + return result; + } + + @Override + public User getUsersById(long userId) { + return userDao.getUsersById(userId); + } +} \ No newline at end of file diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/view/EditUserView.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/view/EditUserView.java new file mode 100644 index 0000000..e6687d9 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/view/EditUserView.java @@ -0,0 +1,33 @@ +package com.javarush.task.task36.task3608.view; + +import com.javarush.task.task36.task3608.bean.User; +import com.javarush.task.task36.task3608.controller.Controller; +import com.javarush.task.task36.task3608.model.ModelData; + +/** + * Created by PAKOT on 12.03.2017. + */ +public class EditUserView implements View { + private Controller controller; + + @Override + public void refresh(ModelData modelData) { + System.out.println("User to be edited:"); + System.out.println("\t" + modelData.getActiveUser().toString()); + System.out.println("==================================================="); + } + + @Override + public void setController(Controller controller) { + this.controller = controller; + } + + public void fireEventUserDeleted(long id){ + controller.onUserDelete(id); + } + + public void fireEventUserChanged(String name, long id, int level){ + controller.onUserChange(name, id, level); + } + +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/view/UsersView.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/view/UsersView.java new file mode 100644 index 0000000..1664257 --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/view/UsersView.java @@ -0,0 +1,46 @@ +package com.javarush.task.task36.task3608.view; + +import com.javarush.task.task36.task3608.bean.User; +import com.javarush.task.task36.task3608.controller.Controller; +import com.javarush.task.task36.task3608.model.ModelData; + +/** + * Created by PAKOT on 11.03.2017. + */ +public class UsersView implements View { + private Controller controller; + + @Override + public void refresh(ModelData modelData) { + if (!modelData.isDisplayDeletedUserList()) { + System.out.println("All users:"); + for (User user : modelData.getUsers()) { + System.out.println("\t" + user.toString()); + } + System.out.println("==================================================="); + } else { + System.out.println("All deleted users:"); + for (User user : modelData.getUsers()) { + System.out.println("\t" + user.toString()); + } + System.out.println("==================================================="); + } + } + + @Override + public void setController(Controller controller) { + this.controller = controller; + } + + public void fireEventShowAllUsers(){ + controller.onShowAllUsers(); + } + + public void fireEventShowDeletedUsers() { + controller.onShowAllDeletedUsers(); + } + + public void fireEventOpenUserEditForm(long id) { + controller.onOpenUserEditForm(id); + } +} diff --git a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/view/View.java b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/view/View.java new file mode 100644 index 0000000..b82324b --- /dev/null +++ b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/view/View.java @@ -0,0 +1,12 @@ +package com.javarush.task.task36.task3608.view; + +import com.javarush.task.task36.task3608.controller.Controller; +import com.javarush.task.task36.task3608.model.ModelData; + +/** + * Created by PAKOT on 11.03.2017. + */ +public interface View { + void refresh(ModelData modelData); + void setController(Controller controller); +} diff --git "a/3.JavaMultithreading/src/com/javarush/task/task36/task3608/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..70746af --- /dev/null +++ "b/3.JavaMultithreading/src/com/javarush/task/task36/task3608/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,144 @@ +taskKey="com.javarush.task.task36.task3608.big09" + +MVC (9) + +Это последнее задание по MVC. + +1. Следуя принципу MVC аналогично реализации предыдущих методов сделай следующее: +напиши логику обновления пользователя. После обновления должен отображаться список пользователей. +Распредели методы по классам MVC, используя следующие сигнатуры публичных методов: +void fireEventUserChanged(String name, long id, int level) +void onUserChange(String name, long id, int level) +void changeUserData(String name, long id, int level) +где name и level - это новые значения для пользователя с выбранным id. +Примечание: метод, который ты собираешься добавить в Вью нужно добавить в EditUserView. + +2. Добавь в main вызов fireEventUserChanged перед вызовом метода fireEventShowDeletedUsers(). + +3. Добавь в интерфейс Model метод, который ты поместил в Модель, реализуй его в FakeModel: выброси UnsupportedOperationException. + + +MVC (8) + +1. Следуя принципу MVC аналогично реализации предыдущих методов сделай следующее: +напиши логику удаления пользователя. После удаления должен отображаться список пользователей. +Распредели методы по классам MVC, используя следующие сигнатуры публичных методов: +void fireEventUserDeleted(long id) +void onUserDelete(long id) +void deleteUserById(long id) +Примечание: метод, который ты собираешься добавить в Вью нужно добавить в EditUserView. + +2. Добавь в main вызов fireEventUserDeleted(124L) перед вызовом метода fireEventShowDeletedUsers(). + +3. Выполни рефакторинг класса MainModel. Теперь, когда есть удаленные пользователи, часть методов стала работать неправильно. +Почти во всех методах, где требуется список пользователей, нужно работать только с активными(живыми) пользователями. +Вынеси в отдельный приватный метод List getAllUsers() получение списка всех пользователей. +Фильтрация активных пользователей у тебя уже есть - метод List filterOnlyActiveUsers(List allUsers). +Отрефактори все методы, которые используют список пользователей. Они должны использовать список живых пользователей. + +4. Добавь в интерфейс Model метод, который ты поместил в Модель, реализуй его в FakeModel: выброси UnsupportedOperationException. + + + +MVC (7) + +1. Распредели методы по классам MVC: + +public void onOpenUserEditForm(long userId) { +...loadUserById(userId); +...refresh(...getModelData()); +} + +public void fireEventOpenUserEditForm(long id) { +...onOpenUserEditForm(id); +} + +public void loadUserById(long userId) { +User user = userService.getUsersById(userId); +...setActiveUser(user); +} + +!!!! Пользователь видит Вью со списком пользователей, нажимает на одного из них, запрос идет на сервер, +выгребаем новые данные и отображаем другую Вью, которая относится к одному выбранному пользователю. +Учти это при реализации этого задания. + +2. Добавь в метод main открытие формы редактирования для пользователя с id=126 перед вызовом метода fireEventShowDeletedUsers(). + +3. Добавь в интерфейс Model метод, который ты поместил в Модель, реализуй его в FakeModel: выброси UnsupportedOperationException. + + + +MVC (6) + +Функционал отображения удаленных пользователей есть, а самих таких пользователей нет. Давай это исправим. +Давай сделаем новую Вью, которая будет отвечать за редактирование одного конкретного пользователя. +UsersView отображает список пользователей. +EditUserView будет отображать данные о редактировании конкретного пользователя. +Для этого нам сначала нужен этот выбранный пользователь. +Как и любые данные его поместим в ModelData. + +1. Создай в ModelData поле User activeUser с геттером и сеттером (Alt+Insert -> Getter and Setter). + +2. Аналогично UsersView создай EditUserView. +Логика метода refresh: +2.1. Вывести в консоль "User to be edited:". +2.2. С новой строки вывести табуляцию и активного пользователя. +2.3. С новой строки вывести разделитель "===================================================". + +3. Создай в контроллере поле EditUserView editUserView с сеттером. + +Когда наши данные выводятся в консоль, то совсем не понятно, список каких пользователей - удаленных или нет - выводится. +Давай сделаем так, чтобы Вью отображала эту информацию. Все данные для отображения хранятся в Моделе. Поэтому: +4. создай в ModelData поле boolean displayDeletedUserList с геттером и сеттером. + +5. Измени метод refresh в UsersView так, чтобы он отображал "All users:" либо "All deleted users:" +в зависимости от того, какие пользователи находятся в списке. Добавь в необходимые методы модели изменение displayDeletedUserList. + + + +MVC (5) + +В сервисе есть метод, который возвращает всех удаленных пользователей. Давай их отобразим. + +1. Распредели методы по классам MVC: + +public void fireEventShowDeletedUsers() { +...onShowAllDeletedUsers(); +} + +public void onShowAllDeletedUsers() { +...loadDeletedUsers(); +} + +public void loadDeletedUsers() { +List users = userService.getAllDeletedUsers(); +} + +Не забудь, что данные, полученные с сервера, необходимо положить в ModelData. А потом обновить view. +Добавь это самостоятельно в нужные методы. + +2. Добавь в Solution.main вызов нового метода, который ты поместил в view. + +3. Добавь в интерфейс Model метод, который ты поместил в Модель, реализуй его в FakeModel: выброси UnsupportedOperationException. + + + +MVC (4) + +Пора заменять нашу фейковую Модель на реальную, которая будет получать данные из DataSource. +В пакет model.service я добавил сервис для работы с пользователями. +Также в корне этой задачи ты найдешь утильный класс Util. + +1. Аналогично FakeModel создай модель MainModel. + +2. Т.к. Модель обращается к сервисам, то в MainModel создай поле UserService userService, инициализируй объектом. + +3. Реализуй логику метода loadUsers: +3.1. Достань всех пользователей между 1 и 100 уровнями. (Метод getUsersBetweenLevels(1, 100)). +3.2. Положи всех пользователей в modelData. + +4. Обнови Solution.main: замени FakeModel на MainModel. +Преимущества MVC в том, что в любой момент времени легко можно заменить любую часть паттерна. + + + diff --git a/4.JavaCollections/4.JavaCollections.iml b/4.JavaCollections/4.JavaCollections.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/4.JavaCollections/4.JavaCollections.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/4.JavaCollections/src/Quest.info b/4.JavaCollections/src/Quest.info new file mode 100644 index 0000000..ee4da74 --- /dev/null +++ b/4.JavaCollections/src/Quest.info @@ -0,0 +1 @@ +Коллекции Java \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task20/task2028/CustomTree.java b/4.JavaCollections/src/com/javarush/task/task20/task2028/CustomTree.java index e43d49f..34cc80f 100644 --- a/4.JavaCollections/src/com/javarush/task/task20/task2028/CustomTree.java +++ b/4.JavaCollections/src/com/javarush/task/task20/task2028/CustomTree.java @@ -1,18 +1,205 @@ package com.javarush.task.task20.task2028; -import java.util.List; +import java.io.Serializable; +import java.util.*; /* Построй дерево(1) */ -public class CustomTree { +public class CustomTree extends AbstractList implements Cloneable, Serializable { + static Entry root = new Entry("0"); + private int size = 0; + private Queue> queue = new LinkedList<>(); + { + queue.add(root); + } + public static void main(String[] args) { -/* List list = new CustomTree(); + List list = new CustomTree(); + //CustomTree list = new CustomTree(); for (int i = 1; i < 16; i++) { list.add(String.valueOf(i)); } //System.out.println("Expected 3, actual is " + ((CustomTree) list).getParent("8")); - list.remove("5"); - //System.out.println("Expected null, actual is " + ((CustomTree) list).getParent("11"));*/ + list.remove("3"); + list.add("16"); + //System.out.println(list.size()); + //System.out.println("Expected null, actual is " + ((CustomTree) list).getParent("11")); + + + } + + + + @Override + public String get(int index) { + throw new UnsupportedOperationException(); + } + + @Override + public String set(int index, String element) { + throw new UnsupportedOperationException(); + } + + @Override + public void add(int index, String s) { + throw new UnsupportedOperationException(); + } + + @Override + public String remove(int index){ + throw new UnsupportedOperationException(); } + + @Override + public List subList(int fromIndex, int toIndex){ + throw new UnsupportedOperationException(); + } + + @Override + protected void removeRange(int fromIndex, int toIndex){ + throw new UnsupportedOperationException(); + } + + @Override + public boolean addAll(int index, Collection c){ + throw new UnsupportedOperationException(); + } + + @Override + public int size() { + //return queue.size() - 1; + //return recurrSize(root) - 1; + return size; + } + + private int recurrSize(Entry entry){ + if (entry.availableToAddLeftChildren) { + if (entry.availableToAddRightChildren) { return 1; } + else { return 1 + recurrSize(entry.rightChild); } + } else if (entry.availableToAddRightChildren) { + return 1 + recurrSize(entry.leftChild); + } else { + return 1 + recurrSize(entry.leftChild) + recurrSize(entry.rightChild); + } + } + + public boolean add(String s){ + + for (Entry entry: queue) { + if (entry.isAvailableToAddChildren()) { + if (entry.availableToAddLeftChildren) { + entry.leftChild = new Entry(s); + if (!"0".equals(entry.elementName)) { + entry.leftChild.parent = entry; + } + size++; + queue.add(entry.leftChild); + entry.checkChildren(); + + return true; + }else { + entry.rightChild = new Entry(s); + if (!"0".equals(entry.elementName)) { + entry.rightChild.parent = entry; + } + entry.checkChildren(); + size++; + queue.add(entry.rightChild); + return true; + } + } + } + return false; + } + + public String getParent(String s){ + for (Entry entry : queue){ + if (s.equals(entry.elementName)) { + return entry.parent.elementName; + } + } + return null; + } + + private int getDepth(int index){ + int power = 0; + int value = 0; + while (value + (int) Math.round(Math.pow(2, power)) < index + 1){ + value = value + (int) Math.round(Math.pow(2, power)); + power += 1; + + } + return power; + } + + @Override + public boolean remove(Object o) { + return remove((String) o); + } + + public boolean remove(String s){ + + Entry forRemove = null; + for (Entry entry: queue){ + if (s.equals(entry.elementName)) { + forRemove = entry; + break; + } + } + if (forRemove != null){ + recurrRemove(forRemove); + if (forRemove.parent.leftChild.elementName.equals(forRemove.elementName)){ + forRemove.parent.leftChild = null; + return true; + } else { + forRemove.parent.rightChild = null; + return true; + } + //queue.remove(forRemove); + } else { return false; } + + } + + private void recurrRemove(Entry entry){ + if (!entry.isAvailableToAddChildren()) { + recurrRemove(entry.rightChild); + recurrRemove(entry.leftChild); + queue.remove(entry); + size--; + }else if (!entry.availableToAddLeftChildren){ + recurrRemove(entry.leftChild); + queue.remove(entry); + size--; + }else { + queue.remove(entry); + size--; + } + } + + static class Entry implements Serializable{ + String elementName; + int lineNumber; + boolean availableToAddLeftChildren; + boolean availableToAddRightChildren; + Entry parent; + Entry leftChild; + Entry rightChild; + + public Entry(String elementName) { + this.elementName = elementName; + availableToAddLeftChildren = true; + availableToAddRightChildren = true; + } + + void checkChildren(){ + if (leftChild != null) { availableToAddLeftChildren = false; } + if (rightChild != null) { availableToAddRightChildren = false; } + } + boolean isAvailableToAddChildren() { + if (availableToAddLeftChildren || availableToAddRightChildren) { return true; } + else { return false; } + } + } + } diff --git "a/4.JavaCollections/src/com/javarush/task/task20/task2028/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task20/task2028/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..aaf630b --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task20/task2028/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,80 @@ +taskKey="com.javarush.task.task20.task2028.big04" + +Построй дерево(4) + +Итак, основа дерева создана, пора тебе поработать немного самому. +Вспомним как должно выглядеть наше дерево. + +Элементы дерева должны следовать так как показано на картинке: +http://info.javarush.ru/uploads/images/00/04/89/2014/03/21/ee9a9b.jpg + +Необходимо написать методы, которые бы позволили создать такую структуру дерева и проводить операции над ней. +Тебе необходимо реализовать: +1) метод add(String s) - добавляет элементы дерева, в качестве параметра принимает имя элемента(elementName), искать место для вставки начинаем слева направо. +2) метод remove(String s) - удаляет элемент дерева имя которого было полученного в качестве параметра. +3) метод size() - возвращает текущее количество элементов в дереве. +4) метод getParent(String s) - возвращает имя родителя элемента дерева, имя которого было полученного в качестве параметра. + + +Требования: +1. После добавления N элементов в дерево с помощью метода add, метод size должен возвращать N. +2. После удаления последнего добавленного элемента из дерева с помощью метода remove, метод size должен возвращать N-1. +3. После удаления второго элемента добавленного в дерево, метод size должен возвращать N/2 + 1 (для случаев где N > 2 и является степенью двойки), N - размер дерева до удаления. +4. Метод getParent должен возвращать имя родителя для любого элемента дерева. + + +Построй дерево(3) + +Класс описывающий дерево мы создали, теперь нужен класс описывающий тип элементов дерева: +1) В классе CustomTree создай вложенный статический параметризированный класс Entry с модификатором доступа по умолчанию. +2) Обеспечь поддержку этим классом интерфейса Serializable. +3) Создай такие поля (модификатор доступа по умолчанию): +- String elementName; +- int lineNumber; +- boolean availableToAddLeftChildren, availableToAddRightChildren; +- Entry parent, leftChild, rightChild; +4) Реализуй публичный конструктор с одним параметром типа String: +- установи поле elementName равным полученному параметру; +- установи поле availableToAddLeftChildren равным true; +- установи поле availableToAddRightChildren равным true; +5) Реализуй метод void checkChildren, устанавливающий поле availableToAddLeftChildren в false, если leftChild не равен null +и availableToAddRightChildren в false, если rightChild не равен null. +6) Реализуй метод boolean isAvailableToAddChildren, возвращающий дизъюнкцию полей availableToAddLeftChildren и availableToAddRightChildren. + +Любое дерево начинается с корня, поэтому не забудь в класс CustomTree добавить поле root типа Entry c модификатором доступа по умолчанию. + + + +Построй дерево(2) + +Несмотря на то что наше дерево является потомком класса AbstractList, это не список в привычном понимании. +В частности нам недоступны принимающие в качестве параметра индекс элемента. +Такие методы необходимо переопределить и бросить новое исключение типа UnsupportedOperationException. + +Вот их список: +public String get(int index) +public String set(int index, String element) +public void add(int index, String element) +public String remove(int index) +public List subList(int fromIndex, int toIndex) +protected void removeRange(int fromIndex, int toIndex) +public boolean addAll(int index, Collection c) + + + +Построй дерево(1) + +Амиго, похоже ты уже достаточно окреп. Самое время проверить свои навыки в большой задаче! +Сегодня реализуем свое дерево немного нестандартным способом(на базе AbstractList). +Вводную информацию можешь получить используя свой любимый поисковик и текст ниже. + +Элементы дерева должны следовать так как показано на картинке: +http://info.javarush.ru/uploads/images/00/04/89/2014/03/21/ee9a9b.jpg + +Для начала сделаем наше дерево потомком класса AbstractList с параметром типа String, а также +реализуем интерфейсы Cloneable и Serializable. + +Реализацию методов get(int index) и size() пока оставь стандартной. + + + diff --git a/4.JavaCollections/src/com/javarush/task/task25/task2515/BaseObject.java b/4.JavaCollections/src/com/javarush/task/task25/task2515/BaseObject.java new file mode 100644 index 0000000..35d64e5 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task25/task2515/BaseObject.java @@ -0,0 +1,92 @@ +package com.javarush.task.task25.task2515; + +/** + * Базовый класс для всех объектов игры. + */ +public abstract class BaseObject { + //координаты + protected double x; + protected double y; + //радиус объекта + protected double radius; + //состояние объект - жив ли объект + private boolean isAlive; + + public BaseObject(double x, double y, double radius) { + this.x = x; + this.y = y; + this.radius = radius; + this.isAlive = true; + } + + public double getX() { + return x; + } + + public void setX(double x) { + this.x = x; + } + + public double getY() { + return y; + } + + public void setY(double y) { + this.y = y; + } + + public double getRadius() { + return radius; + } + + public void setRadius(double radius) { + this.radius = radius; + } + + /** + * Метод рисует свой объект на "канвасе". + */ + public void draw(Canvas canvas) { + //do nothing + } + + /** + * Двигаем себя на один ход. + */ + public void move() { + //do nothing + } + + /** + * Проверяем - не выходит ли (x,y) за границы. + */ + public void checkBorders(double minx, double maxx, double miny, double maxy) { + if (x < minx) x = minx; + if (x > maxx) x = maxx; + if (y < miny) y = miny; + if (y > maxy) y = maxy; + } + + public boolean isAlive() { + return isAlive; + } + + public void setAlive(boolean alive) { + isAlive = alive; + } + + public void die() { + isAlive = false; + } + + /** + * Проверяем - пересекаются ли переданный(o) и наш(this) объекты. + */ + public boolean isIntersect(BaseObject o) { + double dx = x - o.x; + double dy = y - o.y; + double destination = Math.sqrt(dx * dx + dy * dy); + double destination2 = Math.max(radius, o.radius); + return destination <= destination2; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task25/task2515/Bomb.java b/4.JavaCollections/src/com/javarush/task/task25/task2515/Bomb.java new file mode 100644 index 0000000..4f97436 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task25/task2515/Bomb.java @@ -0,0 +1,26 @@ +package com.javarush.task.task25.task2515; + +/** + * Класс для бомбы. + */ +public class Bomb extends BaseObject { + public Bomb(double x, double y) { + super(x, y, 1); + } + + /** + * Отрисовываем себя на холсте. + */ + @Override + public void draw(Canvas canvas) { + canvas.setPoint(x, y, 'B'); + } + + /** + * Двигаем себя вниз на один ход. + */ + @Override + public void move() { + y++; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task25/task2515/Canvas.java b/4.JavaCollections/src/com/javarush/task/task25/task2515/Canvas.java new file mode 100644 index 0000000..12500b2 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task25/task2515/Canvas.java @@ -0,0 +1,66 @@ +package com.javarush.task.task25.task2515; + + +public class Canvas { + private int width; + private int height; + private char[][] matrix; + + public Canvas(int width, int height) { + this.width = width; + this.height = height; + this.matrix = new char[height + 2][width + 2]; + } + + public void clear() { + this.matrix = new char[height + 2][width + 2]; + } + + public void drawMatrix(double x, double y, int[][] matrix, char c) { + for (int i = 0; i < matrix.length; i++) { + for (int j = 0; j < matrix[0].length; j++) { + if (matrix[i][j] != 0) { + setPoint(x + j, y + i, c); + } + } + } + } + + public void setPoint(double x, double y, char c) { + int xRounded = (int) Math.round(x); + int yRounded = (int) Math.round(y); + if (xRounded >= 0 && xRounded < matrix[0].length && yRounded >= 0 && yRounded < matrix.length) { + matrix[yRounded][xRounded] = c; + } + } + + public void print() { + System.out.println(); + + for (int i = 0; i < height + 2; i++) { + for (int j = 0; j < width + 2; j++) { + System.out.print(" "); + System.out.print(matrix[i][j]); + System.out.print(" "); + } + + System.out.println(); + } + + System.out.println(); + System.out.println(); + System.out.println(); + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public char[][] getMatrix() { + return matrix; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task25/task2515/KeyboardObserver.java b/4.JavaCollections/src/com/javarush/task/task25/task2515/KeyboardObserver.java new file mode 100644 index 0000000..404e739 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task25/task2515/KeyboardObserver.java @@ -0,0 +1,70 @@ +package com.javarush.task.task25.task2515; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.util.Queue; +import java.util.concurrent.ArrayBlockingQueue; + +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; + +public class KeyboardObserver extends Thread { + private Queue keyEvents = new ArrayBlockingQueue(100); + + private JFrame frame; + + @Override + public void run() { + frame = new JFrame("KeyPress Tester"); + frame.setTitle("Transparent JFrame Demo"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + frame.setUndecorated(true); + frame.setSize(400, 400); + frame.setExtendedState(JFrame.MAXIMIZED_BOTH); + frame.setLayout(new GridBagLayout()); + + frame.setOpacity(0.0f); + frame.setVisible(true); + + frame.addFocusListener(new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + //do nothing + } + + @Override + public void focusLost(FocusEvent e) { + System.exit(0); + } + }); + + + frame.addKeyListener(new KeyListener() { + + public void keyTyped(KeyEvent e) { + //do nothing + } + + public void keyReleased(KeyEvent e) { + //do nothing + } + + public void keyPressed(KeyEvent e) { + keyEvents.add(e); + } + }); + } + + + public boolean hasKeyEvents() { + return !keyEvents.isEmpty(); + } + + public KeyEvent getEventFromTop() { + return keyEvents.poll(); + } +} + diff --git a/4.JavaCollections/src/com/javarush/task/task25/task2515/Rocket.java b/4.JavaCollections/src/com/javarush/task/task25/task2515/Rocket.java new file mode 100644 index 0000000..05f9327 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task25/task2515/Rocket.java @@ -0,0 +1,27 @@ +package com.javarush.task.task25.task2515; + +/** + * Класс для объектов-ракета + */ +public class Rocket extends BaseObject { + + public Rocket(double x, double y) { + super(x, y, 1); + } + + /** + * Метод рисует свой объект на "канвасе". + */ + @Override + public void draw(Canvas canvas) { + canvas.setPoint(x, y, 'R'); + } + + /** + * Двигаем себя вверх на один ход. + */ + @Override + public void move() { + y--; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task25/task2515/Space.java b/4.JavaCollections/src/com/javarush/task/task25/task2515/Space.java new file mode 100644 index 0000000..103bf61 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task25/task2515/Space.java @@ -0,0 +1,246 @@ +package com.javarush.task.task25.task2515; + +import java.awt.event.KeyEvent; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +/** + * Главный класс игры - Космос (Space) + */ +public class Space { + //Ширина и высота игрового поля + private int width; + private int height; + + //Космический корабль + private SpaceShip ship; + //Список НЛО + private ArrayList ufos = new ArrayList(); + //Список бомб + private ArrayList bombs = new ArrayList(); + //Список ракет + private ArrayList rockets = new ArrayList(); + + public Space(int width, int height) { + this.width = width; + this.height = height; + } + + /** + * Основной цикл программы. + * Тут происходят все важные действия + */ + public void run() { + //Создаем холст для отрисовки. + Canvas canvas = new Canvas(width, height); + + //Создаем объект "наблюдатель за клавиатурой" и стартуем его. + KeyboardObserver keyboardObserver = new KeyboardObserver(); + keyboardObserver.start(); + + //Игра работает, пока корабль жив + while (ship.isAlive()) { + //"наблюдатель" содержит события о нажатии клавиш? + if (keyboardObserver.hasKeyEvents()) { + KeyEvent event = keyboardObserver.getEventFromTop(); + //Если "стрелка влево" - сдвинуть фигурку влево + System.out.print(event.getKeyCode()); + if (event.getKeyCode() == KeyEvent.VK_LEFT) + ship.moveLeft(); + //Если "стрелка вправо" - сдвинуть фигурку вправо + else if (event.getKeyCode() == KeyEvent.VK_RIGHT) + ship.moveRight(); + //Если "пробел" - запускаем шарик + else if (event.getKeyCode() == KeyEvent.VK_SPACE) + ship.fire(); + } + + //двигаем все объекты игры + moveAllItems(); + + //проверяем столкновения + checkBombs(); + checkRockets(); + //удаляем умершие объекты из списков + removeDead(); + + //Создаем НЛО (1 раз в 10 ходов) + createUfo(); + + //Отрисовываем все объекты на холст, а холст выводим на экран + canvas.clear(); + draw(canvas); + canvas.print(); + + //Пауза 300 миллисекунд + Space.sleep(300); + } + + //Выводим сообщение "Game Over" + System.out.println("Game Over!"); + } + + /** + * Двигаем все объекты игры + */ + public void moveAllItems() { + //нужно получить список всех игрвых объектов и у каждого вызвать метод move(). + List list = game.getAllItems(); + for (BaseObject entry:list){ + entry.move(); + } + } + + /** + * Метод возвращает общий список, который содержит все объекты игры + */ + public List getAllItems() { + //нужно создать новый список и положить в него все игровые объекты. + List list = new ArrayList<>(); + list.addAll(game.getBombs()); + list.addAll(game.getUfos()); + list.addAll(game.getRockets()); + list.add(game.getShip()); + return list; + } + + /** + * Создаем новый НЛО. 1 раз на 10 вызовов. + */ + + public void createUfo() { + if (ufos.size() > 0) return; + + int random10 = (int) (Math.random() * 10); + if (random10 == 0) { + double x = Math.random() * width; + double y = Math.random() * height / 2; + ufos.add(new Ufo(x, y)); + } + } + + /** + * Проверяем бомбы. + * а) столкновение с кораблем (бомба и корабль умирают) + * б) падение ниже края игрового поля (бомба умирает) + */ + public void checkBombs() { + //тут нужно проверить все возможные столкновения для каждой бомбы. + for (Bomb entry:bombs){ + if (ship.isIntersect(entry)) { + ship.die(); + entry.die(); + } + if (entry.getY() > height) { + entry.die(); + } + } + + } + + /** + * Проверяем рокеты. + * а) столкновение с НЛО (ракета и НЛО умирают) + * б) вылет выше края игрового поля (ракета умирает) + */ + public void checkRockets() { + //тут нужно проверить все возможные столкновения для каждой ракеты. + for (BaseObject rocket:rockets){ + for (BaseObject ufo:ufos){ + if (rocket.isIntersect(ufo)){ + rocket.die(); + ufo.die(); + } + } + if (rocket.getY() < 0) { rocket.die(); } + } + } + + /** + * Удаляем умерсшие объекты (бомбы, ракеты, НЛО) из списков + */ + public void removeDead() { + //тут нужно удалить все умершие объекты из списков. + //Кроме космического корабля - по нему определяем ищет еще игра или нет. + + Iterator iterator = ufos.iterator(); + while (iterator.hasNext()) { + if (!iterator.next().isAlive()){ + iterator.remove(); + } + } + + iterator = bombs.iterator(); + while (iterator.hasNext()) { + if (!iterator.next().isAlive()){ + iterator.remove(); + } + } + + iterator = rockets.iterator(); + while (iterator.hasNext()) { + if (!iterator.next().isAlive()){ + iterator.remove(); + } + } + + } + + /** + * Отрисовка всех объектов игры: + * а) заполняем весь холст точесками. + * б) отрисовываем все объекты на холст. + */ + public void draw(Canvas canvas) { + //тут нужно отрисовать все объекты игры + } + + + public SpaceShip getShip() { + return ship; + } + + public void setShip(SpaceShip ship) { + this.ship = ship; + } + + public ArrayList getUfos() { + return ufos; + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public ArrayList getBombs() { + return bombs; + } + + public ArrayList getRockets() { + return rockets; + } + + public static Space game; + + public static void main(String[] args) throws Exception { + game = new Space(20, 20); + game.setShip(new SpaceShip(10, 18)); + game.run(); + } + + /** + * Метод делает паузу длинной delay миллисекунд. + */ + public static void sleep(int delay) { + try { + Thread.sleep(delay); + } catch (InterruptedException e) { + } + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task25/task2515/SpaceShip.java b/4.JavaCollections/src/com/javarush/task/task25/task2515/SpaceShip.java new file mode 100644 index 0000000..40563b2 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task25/task2515/SpaceShip.java @@ -0,0 +1,64 @@ +package com.javarush.task.task25.task2515; + +/** + * Класс для космического корабля + */ +public class SpaceShip extends BaseObject { + //картинка корабля для отрисовки + private static int[][] matrix = { + {0, 0, 0, 0, 0}, + {0, 0, 1, 0, 0}, + {0, 0, 1, 0, 0}, + {1, 0, 1, 0, 1}, + {1, 1, 1, 1, 1}, + }; + + //вектор движения (-1 влево,+1 вправо) + private double dx = 0; + + public SpaceShip(int x, int y) { + super(x, y, 3); + } + + /** + * Устанавливаем вектор движения влево + */ + public void moveLeft() { + dx = -1; + } + + /** + * Устанавливаем вектор движения вправо + */ + public void moveRight() { + dx = 1; + } + + /** + * Метод рисует свой объект на "канвасе". + */ + @Override + public void draw(Canvas canvas) { + canvas.drawMatrix(x - radius + 1, y - radius + 1, matrix, 'M'); + } + + /** + * Двигаем себя на один ход. + * Проверяем столкновение с границами. + */ + @Override + public void move() { + x = x + dx; + + checkBorders(radius, Space.game.getWidth() - radius + 1, 1, Space.game.getHeight() + 1); + } + + /** + * Стреляем. + * Создаем две ракеты: слева и справа от корабля. + */ + public void fire() { + Space.game.getRockets().add(new Rocket(x - 2, y)); + Space.game.getRockets().add(new Rocket(x + 2, y)); + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task25/task2515/Ufo.java b/4.JavaCollections/src/com/javarush/task/task25/task2515/Ufo.java new file mode 100644 index 0000000..745b021 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task25/task2515/Ufo.java @@ -0,0 +1,53 @@ +package com.javarush.task.task25.task2515; + +/** + * Класс для НЛО + */ +public class Ufo extends BaseObject { + //картинка для отрисовки + private static int[][] matrix = { + {0, 0, 0, 0, 0}, + {0, 0, 1, 0, 0}, + {1, 1, 1, 1, 1}, + {0, 1, 1, 1, 0}, + {0, 0, 0, 0, 0}, + }; + + public Ufo(double x, double y) { + super(x, y, 3); + } + + /** + * Метод рисует свой объект на "канвасе". + */ + @Override + public void draw(Canvas canvas) { + canvas.drawMatrix(x - radius + 1, y - radius + 1, matrix, 'U'); + } + + /** + * Двигаем себя на один ход в случайном направлении. + */ + @Override + public void move() { + double dx = Math.random() * 2 - 1; + double dy = Math.random() * 2 - 1; + + x += dx; + y += dy; + + checkBorders(radius, Space.game.getWidth() - radius + 1, radius - 1, Space.game.getHeight() / 2 - 1); + + int random10 = (int) (Math.random() * 10); + if (random10 == 0) + fire(); + } + + /** + * Стреляем. + * Сбрасываем(создаем) одну бомбу прямо под собой. + */ + public void fire() { + Space.game.getBombs().add(new Bomb(x, y + 3)); + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task25/task2515/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task25/task2515/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..eac1c60 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task25/task2515/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,117 @@ +taskKey="com.javarush.task.task25.task2515.big17" + +Space (17) + +Надо закончить метод draw(). +Поступим по аналогии с методом move - сегодня я напишу его сам. + + +Требования: +1. Перейди на следующий этап задачи. + + +Space (16) + +И еще немного: + +Напиши метод createUfo(): +Если список НЛО пуст - создай один корабль в центре сверху. + +Напиши метод checkBombs(): +Надо проверить - не пересеклись между собой какая-нибудь бомба и корабль. +Если пересеклись - корабль и бомба умирают - die(). +Если бомба упала за границу экрана y > height бомба тоже умирает. + +Напиши метод checkRockets(): +Надо проверить - не пересеклись между собой какая-нибудь ракета и НЛО. +Если пересеклись - ракета и нло умирают - die(). +Если ракета улетела за границу экрана y < 0, ракета тоже умирает. + +Напиши метод removeDead(): +В это методе удали из списков ufos, rockets, bombs все мертвые объекты (isAlive() == false). + + + +Space (15) + +Надо еще закончить класс Space. + +Напиши метод getAllItems: +Метод должен возвращать один общий список всех объектов типа BaseObject. + +Напиши метод moveAllItems: +Метод должен двигать все объекты по одному разу. +Надо: +а) получить список всех объектов типа BaseObject; +б) вызвать у каждого из них метод move(). + + + +Space (14) + +Теперь напиши класс Ufo. +Он чуть сложнее класса Bomb и проще SpaceShip. +Тебе понадобятся методы draw(), move(), fire(). +Также не забудь о конструкторе. Типы параметров double, а радиус ufo будет равен 3. + +Метод draw() сделай по аналогии с SpaceShip. Рисовать UFO будем символом 'U'. +И добавь матрицу, по аналогии с SpaceShip. + +Метод move() надо сделать так: +а) корабль перемещается по случайной траектории; +Подсказка: +double dx = Math.random() * 2 - 1; //-1..1 +double dy = Math.random() * 2 - 1; //-1..1 +б) корабль не опускается в нижнюю половину экрана; +y <= height/2 +в) С вероятностью 10% корабль должен стрелять - вызывать метод fire. + +Метод fire(): +Корабль сбрасывает одну бомбу по середине. +Сделать аналогично классу SpaceShip. + + + +Space (13) + +Теперь перейдем к методам draw, move. +В методе move() надо: +а) увеличить x на dx; +б) проверить, не вылез ли корабль за границы космоса [0, Space.game.getWidth()]. Используй метод checkBorders. +Учти, что ширина корабля равна двум его радиусам. + +Метод draw я напишу сам - просто объяви пустой метод. + +Еще нам понадобится метод fire(), ведь корабль умеет стрелять. +Этот метод вызывается, когда надо произвести выстрел. +В этом методе надо: +а) создать две ракеты; +б) установить им координаты левого края корабля и правого края корабля (пушки находятся на расстоянии 2 от центра корабля); +в) добавить эти ракеты в список ракет объекта game. + +Его можно получить так: +Space.game.getRockets() + + + +Space (12) + +Теперь займемся кораблем. +Для сложности сделаем так: если пользователь нажал кнопку влево, то корабль начинает все время двигаться влево. +Если нажал кнопку вправо - все время в право до упора. +Поэтому заведем специальную переменную dx, которая будет хранить направление движения корабля. +если dx = 1, корабль каждый ход идет на 1 вправо, +если dx = -1, корабль каждый ход идет на 1 влево. +Надо: +а) добавь конструктор, можно такой: +Радиус корабля будет равен 3. Корабль большой - это вам не ракета и не бомба. +public SpaceShip(int x, int y) +{ +super(x, y, 3); +} +б) добавь в класс SpaceShip переменную dx (double, по умолчанию равна 0); +в) метод moveLeft(), устанавливает dx равной -1; +г) метод moveRight(), устанавливает dx равной 1. + + + diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3101/FileUtils.java b/4.JavaCollections/src/com/javarush/task/task31/task3101/FileUtils.java new file mode 100644 index 0000000..401986f --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3101/FileUtils.java @@ -0,0 +1,14 @@ +package com.javarush.task.task31.task3101; + +import java.io.File; + +public class FileUtils { + + public static void deleteFile(File file) { + if (!file.delete()) System.out.println("Can not delete file with name " + file.getName()); + } + + public static void renameFile(File source, File destination) { + if (!source.renameTo(destination)) System.out.println("Can not rename file with name " + source.getName()); + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3101/Solution.java b/4.JavaCollections/src/com/javarush/task/task31/task3101/Solution.java new file mode 100644 index 0000000..02f1b6b --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3101/Solution.java @@ -0,0 +1,65 @@ +package com.javarush.task.task31.task3101; + +import java.io.File; +import java.io.FileOutputStream; + +import java.io.IOException; +import java.nio.file.*; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + +/* +Проход по дереву файлов +*/ +public class Solution { + public static void main(String[] args) { + if (args[0] == null || args[1] == null){ return; } + File baseOutFile = new File(args[1]); + Path dirPath = Paths.get(args[0]); + File outFile = new File(baseOutFile.getParent() + File.separator + "allFilesContent.txt"); + FileUtils.renameFile(baseOutFile, outFile); + ArrayList fileList = new ArrayList<>(); + + try (FileOutputStream outputStream = new FileOutputStream(outFile)) { + Files.walkFileTree(dirPath, new SimpleFileVisitor(){ + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs){ + File currentFile = new File(file.toString()); + if (currentFile.isFile()) { + if (currentFile.length() > 50) { + FileUtils.deleteFile(currentFile); + } else { + fileList.add(currentFile); + } + } + return FileVisitResult.CONTINUE; + } + + }); + + Collections.sort(fileList, new Comparator() { + @Override + public int compare(File o1, File o2) { + return o1.getName().compareTo(o2.getName()); + } + }); + + for (File entry: fileList) { + byte[] content = Files.readAllBytes(entry.toPath()); + outputStream.write(content); + outputStream.write('\n'); + } + + + + } catch (IOException e) { + + } + } + + public static void deleteFile(File file) { + if (!file.delete()) System.out.println("Can not delete file with name " + file.getName()); + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task31/task3101/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task31/task3101/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..52d4290 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task31/task3101/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,23 @@ +taskKey="com.javarush.task.task31.task3101" + +Проход по дереву файлов + +1. На вход метода main подаются два параметра. +Первый - path - путь к директории, второй - resultFileAbsolutePath - имя файла, который будет содержать результат. +2. Для каждого файла в директории path и в ее всех вложенных поддиректориях выполнить следующее: +2.1. Если у файла длина в байтах больше 50, то удалить его (используй метод FileUtils.deleteFile). +2.2. Если у файла длина в байтах НЕ больше 50, то для всех таких файлов: +2.2.1. Отсортировать их по имени файла в возрастающем порядке, путь не учитывать при сортировке. +2.2.2. Переименовать resultFileAbsolutePath в 'allFilesContent.txt' (используй метод FileUtils.renameFile). +2.2.3. В allFilesContent.txt последовательно записать содержимое всех файлов из п. 2.2.1. Тела файлов разделять "n". +Все файлы имеют расширение txt. + + +Требования: +1. Файл, который приходит вторым параметром в main, должен быть переименован в allFilesContent.txt. +2. Нужно создать поток для записи в переименованный файл. +3. Пройдись по всем файлам в директории, которая приходит первым параметром в main, и всех ее поддиректориях. Файлы с размером более 50 байт нужно удалить используя метод FileUtils.deleteFile. +4. Содержимое всех файлов, размер которых не превышает 50 байт, должно быть записано в файл allFilesContent.txt в отсортированном по имени файла порядке. +5. Поток для записи в файл нужно закрыть. + + diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3102/Solution.java b/4.JavaCollections/src/com/javarush/task/task31/task3102/Solution.java new file mode 100644 index 0000000..c82a89e --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3102/Solution.java @@ -0,0 +1,34 @@ +package com.javarush.task.task31.task3102; + +import java.io.IOException; +import java.nio.file.*; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.List; +import java.util.PriorityQueue; +import java.util.Queue; + + +/* +Находим все файлы +*/ +public class Solution { + public static List getFileTree(String root) throws IOException { + //Queue queue = new PriorityQueue<>(); + List list = new ArrayList<>(); + Files.walkFileTree(Paths.get(root), new SimpleFileVisitor(){ + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { + list.add(file.toString()); + return FileVisitResult.CONTINUE; + } + + }); + return list; + + } + + public static void main(String[] args) { + + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task31/task3102/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task31/task3102/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..6850d66 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task31/task3102/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,17 @@ +taskKey="com.javarush.task.task31.task3102" + +Находим все файлы + +Реализовать логику метода getFileTree, который должен в директории root найти список всех файлов включая вложенные. +Используй очередь, рекурсию не используй. +Верни список всех путей к найденным файлам, путь к директориям возвращать не надо. +Путь должен быть абсолютный. + + +Требования: +1. Метод getFileTree должен принимать аргументом String root, по которому нужно найти все вложенные файлы. +2. Метод getFileTree должен возвращать список строк. +3. Нужно реализовать метод getFileTree: найти все файлы по указанному пути и добавить их в список. +4. Метод getFileTree должен быть вызван только 1 раз (рекурсию не использовать). + + diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3103/Solution.java b/4.JavaCollections/src/com/javarush/task/task31/task3103/Solution.java new file mode 100644 index 0000000..e7cf411 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3103/Solution.java @@ -0,0 +1,28 @@ +package com.javarush.task.task31.task3103; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.List; + +/* +Своя реализация +*/ +public class Solution { + public static byte[] readBytes(String fileName) throws IOException { + return Files.readAllBytes(Paths.get(fileName)); + } + + public static List readLines(String fileName) throws IOException { + return Files.readAllLines(Paths.get(fileName)); + } + + public static void writeBytes(String fileName, byte[] bytes) throws IOException { + Files.write(Paths.get(fileName), bytes); + } + + public static void copy(String resourceFileName, String destinationFileName) throws IOException { + Files.copy(Paths.get(resourceFileName), Paths.get(destinationFileName)); + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task31/task3103/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task31/task3103/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..801e0c2 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task31/task3103/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,22 @@ +taskKey="com.javarush.task.task31.task3103" + +Своя реализация + +Реализуй логику методов: +1. readBytes - должен возвращать все байты файла fileName. +2. readLines - должен возвращать все строки файла fileName. Используй кодировку по умолчанию. +3. writeBytes - должен записывать массив bytes в файл fileName. +4. copy - должен копировать файл resourceFileName на место destinationFileName. + +ГЛАВНОЕ УСЛОВИЕ: +Никаких других импортов! + + +Требования: +1. Импорты в классе Solution менять нельзя. +2. Метод readBytes должен возвращать все байты файла fileName. +3. Метод readLines должен возвращать все строки файла fileName с кодировкой по умолчанию. +4. Метод writeBytes должен записывать массив bytes в файл fileName. +5. Метод copy должен копировать файл resourceFileName на место destinationFileName. + + diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3104/Solution.java b/4.JavaCollections/src/com/javarush/task/task31/task3104/Solution.java new file mode 100644 index 0000000..ee7d5db --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3104/Solution.java @@ -0,0 +1,59 @@ +package com.javarush.task.task31.task3104; + +import java.io.File; +import java.io.IOException; +import java.nio.file.*; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; + +/* +Поиск скрытых файлов +*/ +public class Solution extends SimpleFileVisitor { + public static void main(String[] args) throws IOException { + EnumSet options = EnumSet.of(FileVisitOption.FOLLOW_LINKS); + final Solution solution = new Solution(); + Files.walkFileTree(Paths.get("D:/"), options, 20, solution); + + List result = solution.getArchived(); + System.out.println("All archived files:"); + for (String path : result) { + System.out.println("\t" + path); + } + + List failed = solution.getFailed(); + System.out.println("All failed files:"); + for (String path : failed) { + System.out.println("\t" + path); + } + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + if (file.toString().endsWith(".zip") || file.toString().endsWith(".rar")) { + archived.add(file.toString()); + } + return super.visitFile(file, attrs); + } + + @Override + public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { + //FileVisitResult result = super.visitFileFailed(file, exc); + failed.add(file.toString()); + return FileVisitResult.SKIP_SUBTREE; + + } + + private List archived = new ArrayList<>(); + private List failed = new ArrayList<>(); + + public List getArchived() { + return archived; + } + + public List getFailed() { + return failed; + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task31/task3104/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task31/task3104/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..8e82448 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task31/task3104/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,19 @@ +taskKey="com.javarush.task.task31.task3104" + +Поиск скрытых файлов + +В классе Solution переопредели логику двух методов: +-visitFile кроме своей логики должен добавлять в archived все пути к zip и rar файлам +-visitFileFailed должен добавлять в failed все пути к недоступным файлам и возвращать SKIP_SUBTREE +Пример вывода: +D:/mydir/BCD.zip +Метод main не участвует в тестировании + + +Требования: +1. В классе Solution нужно переопределить метод visitFile. +2. Метод visitFile, кроме своей логики, должен добавлять в поле archived все пути к zip и rar файлам. +3. В классе Solution нужно переопределить метод visitFileFailed. +4. Метод visitFileFailed должен добавлять в поле failed все пути к недоступным файлам и возвращать SKIP_SUBTREE. + + diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3105/Solution.java b/4.JavaCollections/src/com/javarush/task/task31/task3105/Solution.java new file mode 100644 index 0000000..e47e458 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3105/Solution.java @@ -0,0 +1,86 @@ +package com.javarush.task.task31.task3105; + + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; + + +/* +Добавление файла в архив +*/ +public class Solution { + private static Map map = new HashMap<>(); + + public static void main(String[] args) throws IOException { + if (args[0] == null || args[1] == null) { return; } + if (!args[1].toString().endsWith(".zip")) { return; } + Path pathToFile = Paths.get(args[0]); + + FileInputStream zipInputAsFile = new FileInputStream(args[1]); + ZipInputStream zipInput = new ZipInputStream(zipInputAsFile); + + + ZipEntry zipEntry; + while ((zipEntry = zipInput.getNextEntry()) != null) { + if (!zipEntry.isDirectory()) { + StringBuilder buffer = new StringBuilder(); + + while (zipInput.available() > 0) { + int symbol = zipInput.read(); + if (symbol != -1) { + buffer.append((char) symbol); + } + } + + map.put(zipEntry.getName(), buffer.toString()); + } + } + zipInput.close(); + zipInputAsFile.close(); + + + + FileOutputStream zipOutAsFile = new FileOutputStream(args[1]); + ZipOutputStream zipOut = new ZipOutputStream(zipOutAsFile); + + boolean isPresent = false; + + for (Map.Entry mapEntry : map.entrySet()) { + zipOut.putNextEntry(new ZipEntry(mapEntry.getKey())); + + if (mapEntry.getKey().contains("/")) { + if (mapEntry.getKey().substring(mapEntry.getKey().lastIndexOf("/") + 1).equals(Paths.get(args[0]).getFileName().toString())){ + Files.copy(Paths.get(args[0]), zipOut); + isPresent = true; + } else { + zipOut.write((mapEntry.getValue().getBytes())); + + } + }else { + if (mapEntry.getKey().equals(Paths.get(args[0]).getFileName().toString())) { + Files.copy(Paths.get(args[0]), zipOut); + isPresent = true; + } else { + zipOut.write((mapEntry.getValue().getBytes())); + } + } + //zipOut.write((mapEntry.getValue().getBytes())); + } + if (!isPresent) { + zipOut.putNextEntry(new ZipEntry("new/" + Paths.get(args[0]).getFileName().toString())); + Files.copy(Paths.get(args[0]), zipOut); + } + + zipOut.close(); + zipOutAsFile.close(); + + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task31/task3105/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task31/task3105/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..4d96869 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task31/task3105/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,36 @@ +taskKey="com.javarush.task.task31.task3105" + +Добавление файла в архив + +В метод main приходит список аргументов. +Первый аргумент - полный путь к файлу fileName. +Второй аргумент - путь к zip-архиву. +Добавить файл (fileName) внутрь архива в директорию 'new'. +Если в архиве есть файл с таким именем, то заменить его. + +Пример входных данных: +C:/result.mp3 +C:/pathToTest/test.zip + +Файлы внутри test.zip: +a.txt +b.txt + +После запуска Solution.main архив test.zip должен иметь такое содержимое: +new/result.mp3 +a.txt +b.txt + +Подсказка: нужно сначала куда-то сохранить содержимое всех энтри, +а потом записать в архив все энтри вместе с добавленным файлом. +Пользоваться файловой системой нельзя. + + +Требования: +1. В методе main создай ZipInputStream для архивного файла (второй аргумент main). Нужно вычитать из него все содержимое. +2. В методе main создай ZipOutputStream для архивного файла (второй аргумент main). +3. В ZipOutputStream нужно записать содержимое файла, который приходит первым аргументом в main. +4. В ZipOutputStream нужно записать все остальное содержимое, которое было вычитано из ZipInputStream. +5. Потоки для работы с архивом должны быть закрыты. + + diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3106/Solution.java b/4.JavaCollections/src/com/javarush/task/task31/task3106/Solution.java new file mode 100644 index 0000000..e5b4bb1 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3106/Solution.java @@ -0,0 +1,51 @@ +package com.javarush.task.task31.task3106; + +import java.io.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +/* +Разархивируем файл +*/ +public class Solution { + public static void main(String[] args) throws IOException { + if (args == null) { return; } + List pathsList = new ArrayList(); + + for (int i = 1; i < args.length; i++) { + pathsList.add(args[i]); + } + + Collections.sort(pathsList, new Comparator() { + @Override + public int compare(String o1, String o2) { + return o1.substring(o1.length() - 3).compareTo(o2.substring(o2.length() - 3)); + } + }); + + List streamsLists = new ArrayList<>(); + for (int i = 0; i < pathsList.size(); i++) { + streamsLists.add(new FileInputStream(pathsList.get(i))); + } + + ZipInputStream fullZipInput = new ZipInputStream(new SequenceInputStream(Collections.enumeration(streamsLists))); + ZipEntry zipEntry = null; + FileOutputStream out = new FileOutputStream(new File(args[0])); + while ((zipEntry = fullZipInput.getNextEntry()) != null) { + int symbol = 0; + int count; + byte[] buff = new byte[1024 * 1024]; + while ((count = fullZipInput.read(buff)) != -1) { + out.write(buff, 0, count); + } + out.flush(); + } + fullZipInput.close(); + out.close(); + + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task31/task3106/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task31/task3106/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..5c6e425 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task31/task3106/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,26 @@ +taskKey="com.javarush.task.task31.task3106" + +Разархивируем файл + +В метод main приходит список аргументов. +Первый аргумент - имя результирующего файла resultFileName, остальные аргументы - имена файлов fileNamePart. +Каждый файл (fileNamePart) - это кусочек zip архива. Нужно разархивировать целый файл, собрав его из кусочков. +Записать разархивированный файл в resultFileName. +Архив внутри может содержать файл большой длины, например, 50Mb. +Внутри архива может содержаться файл с любым именем. + +Пример входных данных. Внутри архива находится один файл с именем abc.mp3: +C:/result.mp3 +C:/pathToTest/test.zip.003 +C:/pathToTest/test.zip.001 +C:/pathToTest/test.zip.004 +C:/pathToTest/test.zip.002 + + +Требования: +1. В методе main нужно создать ZipInputStream для архива, собранного из кусочков файлов. Файлы приходят аргументами в main, начиная со второго. +2. Создай поток для записи в файл, который приходит первым аргументом в main. Запиши туда содержимое файла из архива. +3. Поток для чтения из архива должен быть закрыт. +4. Поток для записи в файл должен быть закрыт. + + diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3107/ConcreteFileData.java b/4.JavaCollections/src/com/javarush/task/task31/task3107/ConcreteFileData.java new file mode 100644 index 0000000..22fabc8 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3107/ConcreteFileData.java @@ -0,0 +1,36 @@ +package com.javarush.task.task31.task3107; + +public class ConcreteFileData implements FileData { + + private boolean hidden; + private boolean executable; + private boolean directory; + private boolean writable; + + public ConcreteFileData(boolean hidden, boolean executable, boolean directory, boolean writable) { + this.hidden = hidden; + this.executable = executable; + this.directory = directory; + this.writable = writable; + } + + @Override + public boolean isHidden() { + return hidden; + } + + @Override + public boolean isExecutable() { + return executable; + } + + @Override + public boolean isDirectory() { + return directory; + } + + @Override + public boolean isWritable() { + return writable; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3107/FileData.java b/4.JavaCollections/src/com/javarush/task/task31/task3107/FileData.java new file mode 100644 index 0000000..30924ad --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3107/FileData.java @@ -0,0 +1,11 @@ +package com.javarush.task.task31.task3107; + +public interface FileData { + boolean isHidden(); + + boolean isExecutable(); + + boolean isDirectory(); + + boolean isWritable(); +} diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3107/NullFileData.java b/4.JavaCollections/src/com/javarush/task/task31/task3107/NullFileData.java new file mode 100644 index 0000000..a59ef39 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3107/NullFileData.java @@ -0,0 +1,33 @@ +package com.javarush.task.task31.task3107; + +public class NullFileData implements FileData { + private Exception exception; + + public NullFileData(Exception e) { + this.exception = e; + } + + public Exception getException() { + return exception; + } + + @Override + public boolean isHidden() { + return false; + } + + @Override + public boolean isExecutable() { + return false; + } + + @Override + public boolean isDirectory() { + return false; + } + + @Override + public boolean isWritable() { + return false; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3107/Solution.java b/4.JavaCollections/src/com/javarush/task/task31/task3107/Solution.java new file mode 100644 index 0000000..0c0455c --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3107/Solution.java @@ -0,0 +1,28 @@ +package com.javarush.task.task31.task3107; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +/* +Null Object Pattern +*/ +public class Solution { + private FileData fileData; + + public Solution(String pathToFile) { + try { + + fileData = new ConcreteFileData(Files.isHidden(Paths.get(pathToFile)), + Files.isExecutable(Paths.get(pathToFile)), + Files.isDirectory(Paths.get(pathToFile)), + Files.isWritable(Paths.get(pathToFile))); + } catch (Exception e) { + fileData = new NullFileData(e); + } + } + + public FileData getFileData() { + return fileData; + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task31/task3107/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task31/task3107/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..d989249 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task31/task3107/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,18 @@ +taskKey="com.javarush.task.task31.task3107" + +Null Object Pattern + +Почитай на вики про паттерн "Null Object". +Используй Files, чтобы в конструкторе класса Solution правильно инициализировать поле fileData объектом ConcreteFileData. +Если возникли какие-то проблемы со чтением файла по пути pathToFile, то инициализируй поле объектом NullFileData. + + +Требования: +1. Конструктор Solution должен инициализировать поле fileData объектом ConcreteFileData. +2. Если в конструкторе Solution возникла ошибка, нужно инициализировать поле fileData объектом NullFileData. +3. Конструктор Solution должен корректно устанавливать значение поля hidden у объекта ConcreteFileData. +4. Конструктор Solution должен корректно устанавливать значение поля executable у объекта ConcreteFileData. +5. Конструктор Solution должен корректно устанавливать значение поля directory у объекта ConcreteFileData. +6. Конструктор Solution должен корректно устанавливать значение поля writable у объекта ConcreteFileData. + + diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3108/Solution.java b/4.JavaCollections/src/com/javarush/task/task31/task3108/Solution.java new file mode 100644 index 0000000..9caf9fd --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3108/Solution.java @@ -0,0 +1,21 @@ +package com.javarush.task.task31.task3108; + +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; + +/* +Исследуем Path +*/ +public class Solution { + public static void main(String[] args) throws IOException { + Path path1 = Paths.get("D:/test/data/firstDir"); + Path path2 = Paths.get("D:/test/data/secondDir/third"); + Path resultPath = getDiffBetweenTwoPaths(path1, path2); + System.out.println(resultPath); //expected output '../secondDir/third' or '..\secondDir\third' + } + + public static Path getDiffBetweenTwoPaths(Path path1, Path path2) { + return path1.relativize(path2); + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task31/task3108/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task31/task3108/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..cd99cd7 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task31/task3108/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,17 @@ +taskKey="com.javarush.task.task31.task3108" + +Исследуем Path + +Почитай про все методы класса Path. +Найди такой, который создает относительный путь между текущим и переданным путем. +Реализуй логику метода getDiffBetweenTwoPaths, он должен возвращать относительный путь. +Метод main не участвует в тестировании. + + +Требования: +1. Класс Solution должен содержать метод Path getDiffBetweenTwoPaths(Path path1, Path path2). +2. Метод Path getDiffBetweenTwoPaths(Path path1, Path path2) должен быть статическим. +3. Метод getDiffBetweenTwoPaths должен возвращать относительный путь между первым аргументом и вторым. +4. Для реализации метода getDiffBetweenTwoPaths используй правильный метод объекта Path. + + diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3109/Solution.java b/4.JavaCollections/src/com/javarush/task/task31/task3109/Solution.java new file mode 100644 index 0000000..969ea47 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3109/Solution.java @@ -0,0 +1,46 @@ +package com.javarush.task.task31.task3109; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileReader; +import java.io.IOException; +import java.net.URL; +import java.util.Properties; + +/* +Читаем конфиги +*/ +public class Solution { + public static void main(String[] args) { + Solution solution = new Solution(); + Properties properties = solution.getProperties("src/com/javarush/task/task31/task3109/properties.xml"); + properties.list(System.out); + + properties = solution.getProperties("src/com/javarush/task/task31/task3109/properties.txt"); + properties.list(System.out); + + properties = solution.getProperties("src/com/javarush/task/task31/task3109/notExists"); + properties.list(System.out); + } + + public Properties getProperties(String fileName) { + Properties properties = new Properties(); + + /*URL className = Solution.class.getProtectionDomain().getCodeSource().getLocation(); + String classPath = className.getPath(); + classPath = classPath.replace("/out/production", ""); + String absoluteStringPath = classPath.substring(1) + fileName;*/ + String absoluteStringPath = fileName; + try { + if ("xml".equals(absoluteStringPath.substring(absoluteStringPath.lastIndexOf(".") + 1))) { + properties.loadFromXML(new FileInputStream(new File(absoluteStringPath))); + } else { + properties.load(new FileReader(absoluteStringPath)); + } + + }catch (IOException e) { + } + + return properties; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3109/properties.txt b/4.JavaCollections/src/com/javarush/task/task31/task3109/properties.txt new file mode 100644 index 0000000..af44458 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3109/properties.txt @@ -0,0 +1,2 @@ +name=Amigo +level=31 diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3109/properties.xml b/4.JavaCollections/src/com/javarush/task/task31/task3109/properties.xml new file mode 100644 index 0000000..f7dfc45 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3109/properties.xml @@ -0,0 +1,6 @@ + + + +Amigo +31 + diff --git "a/4.JavaCollections/src/com/javarush/task/task31/task3109/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task31/task3109/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..e8dc6a1 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task31/task3109/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,19 @@ +taskKey="com.javarush.task.task31.task3109" + +Читаем конфиги + +Реализовать метод getProperties, который должен считывать свойства из переданного файла fileName. +fileName может иметь любое расширение - как xml, так и любое другое, или вообще не иметь. +Нужно обеспечить корректное чтение свойств. +При возникновении ошибок должен возвращаться пустой объект. +Метод main не участвует в тестировании. +Подсказка: возможно тебе понадобится File.separator. + + +Требования: +1. Класс Solution должен содержать метод Properties getProperties(String fileName). +2. Метод getProperties должен корректно считывать свойства из xml-файла. +3. Метод getProperties должен корректно считывать свойства из любого другого файла с любым расширением. +4. Метод getProperties должен возвращать пустой объект, если во время чтения свойств возникла ошибка. + + diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3111/SearchFileVisitor.java b/4.JavaCollections/src/com/javarush/task/task31/task3111/SearchFileVisitor.java new file mode 100644 index 0000000..24ded0e --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3111/SearchFileVisitor.java @@ -0,0 +1,66 @@ +package com.javarush.task.task31.task3111; + +import java.io.File; +import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.List; + +public class SearchFileVisitor extends SimpleFileVisitor { + private int maxSize; + private String partOfName; + private String partOfContent; + private int minSize; + + private List foundFiles = new ArrayList<>(); + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + boolean found = true; + if (maxSize != 0) { + if (Files.size(file) > maxSize) { found = false; } + } + + if (minSize != 0) { + if (Files.size(file) < minSize) { found = false; } + } + + if (partOfName != null) { + if (!(file.getName(file.getNameCount() - 1).toString()).contains(partOfName)) { found = false; } + } + + if (partOfContent != null) { + String content = new String(Files.readAllBytes(file)); + if (!content.contains(partOfContent)) { found = false; } + + + } + + if (found) { + foundFiles.add(file); + } + return super.visitFile(file, attrs); + } + + public void setPartOfName(String partOfName){ + this.partOfName = partOfName; + } + public void setPartOfContent(String partOfContent){ + this.partOfContent = partOfContent; + } + public void setMinSize(int minSize){ + this.minSize = minSize; + + } + public void setMaxSize(int maxSize){ + this.maxSize = maxSize; + } + + public List getFoundFiles(){ + return foundFiles; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3111/Solution.java b/4.JavaCollections/src/com/javarush/task/task31/task3111/Solution.java new file mode 100644 index 0000000..6517e00 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3111/Solution.java @@ -0,0 +1,30 @@ +package com.javarush.task.task31.task3111; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; + +/* +Продвинутый поиск файлов +*/ +public class Solution { + + public static void main(String[] args) throws IOException { + SearchFileVisitor searchFileVisitor = new SearchFileVisitor(); + + searchFileVisitor.setPartOfName("amigo"); + searchFileVisitor.setPartOfContent("programmer"); + searchFileVisitor.setMinSize(500); + searchFileVisitor.setMaxSize(10000); + + Files.walkFileTree(Paths.get("D:/SecretFolder"), searchFileVisitor); + + List foundFiles = searchFileVisitor.getFoundFiles(); + for (Path file : foundFiles) { + System.out.println(file); + } + } + +} diff --git "a/4.JavaCollections/src/com/javarush/task/task31/task3111/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task31/task3111/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..f070a56 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task31/task3111/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,32 @@ +taskKey="com.javarush.task.task31.task3111" + +Продвинутый поиск файлов + +Давай реализуем настраиваемый поиск файлов в директории. +Просмотри интерфейс java.nio.file.FileVisitor и его базовую реализацию java.nio.file.SimpleFileVisitor. +Во время поиска по дереву файлов с помощью метода Files.walkFileTree(Path start, FileVisitor visitor) +мы используем объект FileVisitor для выполнения необходимых операций над найденными объектами Path. + +Наш класс для поиска будет называться SearchFileVisitor и расширять SimpleFileVisitor. + +Поиск можно будет выполнять по таким критериям: +- выражение, встречающееся в названии файла (String); +- выражение, встречающееся в содержимом файла (String); +- максимальный и минимальный размер файла (int). +Можно задавать либо один, либо сразу несколько критериев для поиска. + +Я в main написал код, который использует готовый SearchFileVisitor для поиска файлов, тебе осталась совсем легкая задача - выполнить его реализацию. +Подсказка 1: методы get... , set... - это геттеры и сеттеры полей. Основная логика класса по поиску выполняется в методе visitFile(Path file, BasicFileAttributes attrs). +Подсказка 2: для работы с файлами используй только классы из пакета java.nio. + + +Требования: +1. В классе SearchFileVisitor нужно создать поля partOfName, partOfContent, minSize, maxSize и сеттеры для них. +2. В классе SearchFileVisitor нужно создать поле foundFiles и геттер для него. Поле должно быть сразу инициализировано. +3. Если в SearchFileVisitor задан критерий поиска partOfName, метод visitFile должен добавить файл в foundFiles, если в названии содержится строка partOfName. +4. Если в SearchFileVisitor задан критерий поиска partOfContent, метод visitFile должен добавить файл в foundFiles, если в содержимом встречается строка partOfContent. +5. Если в SearchFileVisitor задан критерий поиска maxSize, метод visitFile должен добавить файл в foundFiles, если размер файла меньше maxSize. +6. Если в SearchFileVisitor задан критерий поиска minSize, метод visitFile должен добавить файл в foundFiles, если размер файла больше maxSize. +7. Метод visitFile должен быть реализован так, чтобы учитывать сразу несколько критериев поиска. + + diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3112/Solution.java b/4.JavaCollections/src/com/javarush/task/task31/task3112/Solution.java new file mode 100644 index 0000000..2c55ddf --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3112/Solution.java @@ -0,0 +1,41 @@ +package com.javarush.task.task31.task3112; + +import com.sun.webkit.network.URLs; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.FileAttribute; + +/* +Загрузчик файлов +*/ +public class Solution { + + public static void main(String[] args) throws IOException { + Path passwords = downloadFile("https://www.amigo.com/ship/secretPassword.txt", Paths.get("D:/MyDownloads")); + + for (String line : Files.readAllLines(passwords)) { + System.out.println(line); + } + } + + public static Path downloadFile(String urlString, Path downloadDirectory) throws IOException { + URL url = new URL(urlString); + Path tempFile = Files.createTempFile("temp", "temp"); + + InputStream input = url.openStream(); + Files.copy(input, tempFile); + String fileName = urlString.substring(urlString.lastIndexOf("/") + 1); + Path outFile = Paths.get(downloadDirectory + File.separator + fileName); + Files.move(tempFile, outFile); + + return outFile; + // implement this method + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task31/task3112/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task31/task3112/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..a1cae6c --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task31/task3112/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,24 @@ +taskKey="com.javarush.task.task31.task3112" + +Загрузчик файлов + +Реализуй метод downloadFile(String urlString, Path downloadDirectory), на вход которого подается ссылка для скачивания файла и папка, куда нужно закачать файл. +Все ссылки имеют вид: +https://yastatic.net/morda-logo/i/citylogos/yandex19-logo-ru.png +http://toogle.com/files/rules.txt +https://pacemook.com/photos/image1.jpg + +Метод должен создать объект URL и загрузить содержимое файла на локальный диск. +Выкачивай сначала во временную директорию, чтобы в случае неуспешной загрузки в твоей директории не оставались недокачанные файлы. +Затем перемести файл в пользовательскую директорию. Имя для файла возьми из ссылки. +Используй только классы и методы из пакета java.nio. + + +Требования: +1. Метод downloadFile должен создавать объект URL для переданной ссылки. +2. Метод downloadFile должен создать временный файл с помощью метода Files.createTempFile. +3. Метод downloadFile должен скачать файл по ссылке во временный файл, используя метод Files.copy. +4. Метод downloadFile должен переместить файл из временной директории в пользовательскую, используя метод Files.move. +5. Имя сохраненного файла должно быть таким же, как в URL-ссылке. + + diff --git a/4.JavaCollections/src/com/javarush/task/task31/task3113/Solution.java b/4.JavaCollections/src/com/javarush/task/task31/task3113/Solution.java new file mode 100644 index 0000000..6baa318 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task31/task3113/Solution.java @@ -0,0 +1,47 @@ +package com.javarush.task.task31.task3113; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.file.*; +import java.nio.file.attribute.BasicFileAttributes; + +/* +Что внутри папки? +*/ +public class Solution { + private static int dirCount; + private static int filesCount; + private static long volume; + + public static void main(String[] args) throws IOException { + BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + String pathToDirectory = reader.readLine(); + reader.close(); + Path path = Paths.get(pathToDirectory); + if (path == null || !Files.isDirectory(path)) { + System.out.println(path.toString() + " - не папка"); + return; + } + Files.walkFileTree(path, new SimpleFileVisitor(){ + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + filesCount++; + volume += Files.size(file); + return super.visitFile(file, attrs); + } + + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException{ + dirCount++; + return super.preVisitDirectory(dir, attrs); + } + }); + + System.out.println("Всего папок - " + (dirCount - 1)); + System.out.println("Всего файлов - " + filesCount); + System.out.println("Общий размер - " + volume); + + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task31/task3113/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task31/task3113/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..5538f22 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task31/task3113/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,25 @@ +taskKey="com.javarush.task.task31.task3113" + +Что внутри папки? + +Напиши программу, которая будет считать подробную информацию о папке и выводить ее на консоль. + +Первым делом считай путь к папке с консоли. +Если введенный путь не является директорией - выведи "[полный путь] - не папка" и заверши работу. +Затем посчитай и выведи следующую информацию: + +Всего папок - [количество папок в директории] +Всего файлов - [количество файлов в директории и поддиректориях] +Общий размер - [общее количество байт, которое хранится в директории] + +Используй только классы и методы из пакета java.nio. + + +Требования: +1. Метод main должен считывать путь к папке с консоли. +2. Если введенный путь не является директорией - нужно вывести "[полный путь] - не папка" и завершить работу. +3. На консоль должна быть выведена следующая информация: "Всего папок - [количество папок в директории]". +4. На консоль должна быть выведена следующая информация: "Всего файлов - [количество файлов в директории и поддиректориях]". +5. На консоль должна быть выведена следующая информация: "Общий размер - [общее количество байт, которое хранится в директории]". + + diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3201/Solution.java b/4.JavaCollections/src/com/javarush/task/task32/task3201/Solution.java new file mode 100644 index 0000000..b473fe3 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3201/Solution.java @@ -0,0 +1,24 @@ +package com.javarush.task.task32.task3201; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/* +Запись в существующий файл +*/ +public class Solution { + public static void main(String... args) { + if (args[0] == null || args[1] == null || args[2] == null) { return; } + try ( RandomAccessFile raf = new RandomAccessFile(args[0], "rw"); + ) { + if (args[2].length() + Integer.parseInt(args[1]) > raf.length()) { + raf.seek(raf.length()); + raf.write(args[2].getBytes()); + }else { + raf.seek(Integer.parseInt(args[1])); + raf.write(args[2].getBytes()); + } + } catch (IOException e) { + } + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task32/task3201/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task32/task3201/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..3a5ffd8 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task32/task3201/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,20 @@ +taskKey="com.javarush.task.task32.task3201" + +Запись в существующий файл + +В метод main приходят три параметра: +1) fileName - путь к файлу; +2) number - число, позиция в файле; +3) text - текст. +Записать text в файл fileName начиная с позиции number. Запись должна производиться поверх старых данных, содержащихся в файле. +Если файл слишком короткий, то записать в конец файла. +Используй RandomAccessFile и его методы seek и write. + + +Требования: +1. В методе main класса Solution необходимо использовать RandomAccessFile. +2. В методе main класса Solution программа должна записывать данные в файл при помощи метода метода write класса RandomAccessFile. +3. Запись в файл должна происходить с указанной позиции с заменой содержимого. +4. Если файл слишком короткий, то запись text должна происходить в конец файла. + + diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3202/Solution.java b/4.JavaCollections/src/com/javarush/task/task32/task3202/Solution.java new file mode 100644 index 0000000..2b47af3 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3202/Solution.java @@ -0,0 +1,29 @@ +package com.javarush.task.task32.task3202; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; + +/* +Читаем из потока +*/ +public class Solution { + public static void main(String[] args) throws IOException { + //StringWriter writer = getAllDataFromInputStream(new FileInputStream("F:\\JavaProjects\\InputSource\\raf.txt")); + StringWriter writer = getAllDataFromInputStream(new FileInputStream("testFile.log")); + System.out.println(writer.toString()); + } + + public static StringWriter getAllDataFromInputStream(InputStream is) throws IOException { + StringWriter writer = new StringWriter(); + StringBuilder strB = new StringBuilder(); + if (is != null) { + while (is.available() > 0) { + strB.append((char) is.read()); + } + writer.write(strB.toString()); + } + return writer; + } +} \ No newline at end of file diff --git "a/4.JavaCollections/src/com/javarush/task/task32/task3202/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task32/task3202/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..475ecee --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task32/task3202/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,16 @@ +taskKey="com.javarush.task.task32.task3202" + +Читаем из потока + +Реализуй логику метода getAllDataFromInputStream. Он должен вернуть StringWriter, содержащий все данные из переданного потока. +Возвращаемый объект ни при каких условиях не должен быть null. +Метод main не участвует в тестировании. + + +Требования: +1. Публичный статический метод getAllDataFromInputStream (InputStream) должен существовать. +2. Метод getAllDataFromInputStream (InputStream) должен возвращать StringWriter. +3. Метод getAllDataFromInputStream (InputStream) должен вернуть StringWriter, который содержит все данные из переданного потока. +4. Возвращаемый объект ни при каких условиях не должен быть null. + + diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3203/Solution.java b/4.JavaCollections/src/com/javarush/task/task32/task3203/Solution.java new file mode 100644 index 0000000..3aaacbe --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3203/Solution.java @@ -0,0 +1,20 @@ +package com.javarush.task.task32.task3203; + +import java.io.PrintWriter; +import java.io.StringWriter; + +/* +Пишем стек-трейс +*/ +public class Solution { + public static void main(String[] args) { + String text = getStackTrace(new IndexOutOfBoundsException("fff")); + System.out.println(text); + } + + public static String getStackTrace(Throwable throwable) { + StringWriter writer = new StringWriter(); + throwable.printStackTrace(new PrintWriter(writer)); + return writer.toString(); + } +} \ No newline at end of file diff --git "a/4.JavaCollections/src/com/javarush/task/task32/task3203/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task32/task3203/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..f9b91d6 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task32/task3203/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,16 @@ +taskKey="com.javarush.task.task32.task3203" + +Пишем стек-трейс + +Реализуй логику метода getStackTrace, который в виде одной строки (одного объекта типа String) должен возвращать весь стек-трейс переданного исключения. +Используй подходящий метод класса Throwable, который поможет записать стек-трейс в StringWriter. +Метод main не участвует в тестировании. + + +Требования: +1. Публичный статический метод String getStackTrace (Throwable) должен существовать. +2. В методе getStackTrace необходимо создать объект типа StringWriter. +3. В методе getStackTrace (Throwable) необходимо использовать метод класса Throwable, который принимает объект типа PrintWriter. +4. Метод getStackTrace (Throwable) должен возвращать весь стек-трейс переданного исключения. + + diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3204/Solution.java b/4.JavaCollections/src/com/javarush/task/task32/task3204/Solution.java new file mode 100644 index 0000000..54799c2 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3204/Solution.java @@ -0,0 +1,39 @@ +package com.javarush.task.task32.task3204; + +import java.io.ByteArrayOutputStream; + +/* +Генератор паролей +*/ +public class Solution { + public static void main(String[] args) { + ByteArrayOutputStream password = getPassword(); + System.out.println(password.toString()); + } + + public static ByteArrayOutputStream getPassword() { + String alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + boolean isAddedLow = false; + boolean isAddedUpper = false; + boolean isAddedNumber = false; + char lowerCaseChar = alphabet.charAt ((int) (Math.random() * 25)); + char upperCaseChar = alphabet.charAt (26 + (int) (Math.random() * 25)); + char number = alphabet.charAt (52 + (int) (Math.random() * 9)); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + for (int i = 0; i < 8; i++){ + if (!isAddedLow) { + out.write((byte)lowerCaseChar); + isAddedLow = true; + }else if (!isAddedNumber) { + out.write((byte) number); + isAddedNumber = true; + }else if (!isAddedUpper) { + out.write((byte) upperCaseChar); + isAddedUpper = true; + }else { + out.write((byte) alphabet.charAt((int) (Math.random() * alphabet.length()) )); + } + } + return out; + } +} \ No newline at end of file diff --git "a/4.JavaCollections/src/com/javarush/task/task32/task3204/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task32/task3204/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..e2354b5 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task32/task3204/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,24 @@ +taskKey="com.javarush.task.task32.task3204" + +Генератор паролей + +Реализуй логику метода getPassword, который должен возвращать ByteArrayOutputStream, в котором будут байты пароля. +Требования к паролю: +1) 8 символов. +2) только цифры и латинские буквы разного регистра. +3) обязательно должны присутствовать цифры, и буквы разного регистра. +Все сгенерированные пароли должны быть уникальные. +Пример правильного пароля: +wMh7smNu + + +Требования: +1. Класс Solution должен содержать метод getPassword(), который возвращает ByteArrayOutputStream со сгенерированным паролем. +2. Длина пароля должна составлять 8 символов. +3. Пароль должен содержать хотя бы одну цифру. +4. Пароль должен содержать хотя бы одну латинскую букву нижнего регистра. +5. Пароль должен содержать хотя бы одну латинскую букву верхнего регистра. +6. Пароль не должен содержать других символов, кроме цифр и латинских букв разного регистра. +7. Сгенерированные пароли должны быть уникальными. + + diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3205/CustomInvocationHandler.java b/4.JavaCollections/src/com/javarush/task/task32/task3205/CustomInvocationHandler.java new file mode 100644 index 0000000..8cfec3b --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3205/CustomInvocationHandler.java @@ -0,0 +1,23 @@ +package com.javarush.task.task32.task3205; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; + +/** + * Created by Archmage on 22.05.2017. + */ +public class CustomInvocationHandler implements InvocationHandler { + private SomeInterfaceWithMethods someInterfaceWithMethods; + + public CustomInvocationHandler(SomeInterfaceWithMethods someInterfaceWithMethods){ + this.someInterfaceWithMethods = someInterfaceWithMethods; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + System.out.println(method.getName() + " in"); + Object returnObj = method.invoke(someInterfaceWithMethods, args); + System.out.println(method.getName() + " out"); + return returnObj; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3205/Solution.java b/4.JavaCollections/src/com/javarush/task/task32/task3205/Solution.java new file mode 100644 index 0000000..b2c7c28 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3205/Solution.java @@ -0,0 +1,31 @@ +package com.javarush.task.task32.task3205; + +import java.lang.reflect.Proxy; + +/* +Создание прокси-объекта +*/ +public class Solution { + public static void main(String[] args) { + SomeInterfaceWithMethods obj = getProxy(); + obj.stringMethodWithoutArgs(); + obj.voidMethodWithIntArg(1); + + /* expected output + stringMethodWithoutArgs in + inside stringMethodWithoutArgs + stringMethodWithoutArgs out + voidMethodWithIntArg in + inside voidMethodWithIntArg + inside voidMethodWithoutArgs + voidMethodWithIntArg out + */ + } + + public static SomeInterfaceWithMethods getProxy() { + return (SomeInterfaceWithMethods) Proxy.newProxyInstance( + SomeInterfaceWithMethodsImpl.class.getClassLoader(), + SomeInterfaceWithMethodsImpl.class.getInterfaces(), + new CustomInvocationHandler(new SomeInterfaceWithMethodsImpl())); + } +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3205/SomeInterfaceWithMethods.java b/4.JavaCollections/src/com/javarush/task/task32/task3205/SomeInterfaceWithMethods.java new file mode 100644 index 0000000..c9eabdc --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3205/SomeInterfaceWithMethods.java @@ -0,0 +1,9 @@ +package com.javarush.task.task32.task3205; + +public interface SomeInterfaceWithMethods { + void voidMethodWithoutArgs(); + + String stringMethodWithoutArgs(); + + void voidMethodWithIntArg(int i); +} diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3205/SomeInterfaceWithMethodsImpl.java b/4.JavaCollections/src/com/javarush/task/task32/task3205/SomeInterfaceWithMethodsImpl.java new file mode 100644 index 0000000..1c5ecb1 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3205/SomeInterfaceWithMethodsImpl.java @@ -0,0 +1,17 @@ +package com.javarush.task.task32.task3205; + +public class SomeInterfaceWithMethodsImpl implements SomeInterfaceWithMethods { + public void voidMethodWithoutArgs() { + System.out.println("inside voidMethodWithoutArgs"); + } + + public String stringMethodWithoutArgs() { + System.out.println("inside stringMethodWithoutArgs"); + return null; + } + + public void voidMethodWithIntArg(int i) { + System.out.println("inside voidMethodWithIntArg"); + voidMethodWithoutArgs(); + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task32/task3205/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task32/task3205/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..96a76b5 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task32/task3205/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,23 @@ +taskKey="com.javarush.task.task32.task3205" + +Создание прокси-объекта + +1) В отдельном файле создай публичный класс CustomInvocationHandler, который будет хэндлером при создании прокси-объекта. +2) CustomInvocationHandler должен поддерживать интерфейс InvocationHandler. +3) CustomInvocationHandler должен иметь один публичный конструктор с одним аргументом типа SomeInterfaceWithMethods. +4) Перед вызовом любого метода у оригинального объекта должна выводиться фраза [methodName in]. +5) После вызова любого метода у оригинального объекта должна выводиться фраза [methodName out]. +6) Реализуй логику метода getProxy, который должен создавать прокси (Proxy.newProxyInstance(...)). +См. пример вывода в методе main. +Метод main не участвует в тестировании. + + +Требования: +1. Класс CustomInvocationHandler должен существовать. +2. Класс CustomInvocationHandler должен поддерживать интерфейс InvocationHandler. +3. Класс CustomInvocationHandler должен иметь один публичный конструктор с одним аргументом типа SomeInterfaceWithMethods. +4. Перед вызовом любого метода у оригинального объекта должна выводиться фраза [methodName in]. +5. После вызова любого метода у оригинального объекта должна выводиться фраза [methodName out]. +6. Метод getProxy должен создавать прокси для интерфейса SomeInterfaceWithMethods. + + diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3206/Big.java b/4.JavaCollections/src/com/javarush/task/task32/task3206/Big.java new file mode 100644 index 0000000..816baca --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3206/Big.java @@ -0,0 +1,4 @@ +package com.javarush.task.task32.task3206; + +public interface Big extends Item { +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3206/Item.java b/4.JavaCollections/src/com/javarush/task/task32/task3206/Item.java new file mode 100644 index 0000000..00df753 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3206/Item.java @@ -0,0 +1,4 @@ +package com.javarush.task.task32.task3206; + +public interface Item { +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3206/ItemInvocationHandler.java b/4.JavaCollections/src/com/javarush/task/task32/task3206/ItemInvocationHandler.java new file mode 100644 index 0000000..6ba8188 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3206/ItemInvocationHandler.java @@ -0,0 +1,11 @@ +package com.javarush.task.task32.task3206; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; + +public class ItemInvocationHandler implements InvocationHandler { + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + return null; + } +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3206/Small.java b/4.JavaCollections/src/com/javarush/task/task32/task3206/Small.java new file mode 100644 index 0000000..5b10b28 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3206/Small.java @@ -0,0 +1,4 @@ +package com.javarush.task.task32.task3206; + +public interface Small { +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3206/Solution.java b/4.JavaCollections/src/com/javarush/task/task32/task3206/Solution.java new file mode 100644 index 0000000..3b18403 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3206/Solution.java @@ -0,0 +1,40 @@ +package com.javarush.task.task32.task3206; + +import java.lang.reflect.Proxy; +import java.util.Arrays; + +/* +Дженерики для создания прокси-объекта +*/ +public class Solution { + + public static void main(String[] args) { + Solution solution = new Solution(); + test(solution.getProxy(Item.class)); //true false false + test(solution.getProxy(Item.class, Small.class)); //true false true + test(solution.getProxy(Item.class, Big.class, Small.class));//true true true + test(solution.getProxy(Big.class, Small.class)); //true true true т.к. Big наследуется от Item + test(solution.getProxy(Big.class)); //true true false т.к. Big наследуется от Item + } + + + private static void test(Object proxy) { + boolean isItem = proxy instanceof Item; + boolean isBig = proxy instanceof Big; + boolean isSmall = proxy instanceof Small; + + System.out.format("%b %b %b\n", isItem, isBig, isSmall); + } + + public T getProxy(Class className, Class... supportedInterfaces){ + Class[] interfaces = Arrays.copyOf(supportedInterfaces, supportedInterfaces.length + 1); + interfaces[supportedInterfaces.length] = className; + + T proxy = (T) Proxy.newProxyInstance( + this.getClass().getClassLoader(), + interfaces, + new ItemInvocationHandler()); + + return proxy; + } +} \ No newline at end of file diff --git "a/4.JavaCollections/src/com/javarush/task/task32/task3206/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task32/task3206/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..203ba07 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task32/task3206/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,21 @@ +taskKey="com.javarush.task.task32.task3206" + +Дженерики для создания прокси-объекта + +В классе Solution создай публичный метод getProxy: +1) Метод getProxy должен возвращать прокси для любого интерфейса, который наследуется от Item. +2) getProxy должен иметь два параметра. Первый - класс возвращаемого типа, второй - классы дополнительных интерфейсов (используй аргумент переменной длины ...). +3) Используй ItemInvocationHandler для создания прокси. +Метод main не участвует в тестировании. + + +Требования: +1. В классе Solution должен существовать метод getProxy. +2. Метод getProxy должен иметь два параметра. Первый - класс возвращаемого типа, второй - классы дополнительных интерфейсов. +3. Метод getProxy должен возвращать прокси для любого интерфейса, который наследуется от Item. +4. В методе getProxy при вызове Proxy.newProxyInstance передай this.getClass().getClassLoader() в качестве первого аргумента. +5. В методе getProxy при вызове Proxy.newProxyInstance передай вторым аргументом все интерфейсы, которые прокси должен реализовать. +6. В методе getProxy при вызове Proxy.newProxyInstance передай new ItemInvocationHandler() как третий аргумент. +7. Метод getProxy должен работать согласно с условием. + + diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3207/DoubleString.java b/4.JavaCollections/src/com/javarush/task/task32/task3207/DoubleString.java new file mode 100644 index 0000000..88fa4fd --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3207/DoubleString.java @@ -0,0 +1,8 @@ +package com.javarush.task.task32.task3207; + +import java.rmi.Remote; +import java.rmi.RemoteException; + +public interface DoubleString extends Remote { + String doubleString(String str) throws RemoteException; +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3207/DoubleStringImpl.java b/4.JavaCollections/src/com/javarush/task/task32/task3207/DoubleStringImpl.java new file mode 100644 index 0000000..2dc28ae --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3207/DoubleStringImpl.java @@ -0,0 +1,9 @@ +package com.javarush.task.task32.task3207; + +import java.rmi.RemoteException; + +public class DoubleStringImpl implements DoubleString { + public String doubleString(String str) throws RemoteException { + return str + str; + } +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3207/Solution.java b/4.JavaCollections/src/com/javarush/task/task32/task3207/Solution.java new file mode 100644 index 0000000..8efca6c --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3207/Solution.java @@ -0,0 +1,53 @@ +package com.javarush.task.task32.task3207; + +import java.rmi.AlreadyBoundException; +import java.rmi.NotBoundException; +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +import java.rmi.server.UnicastRemoteObject; + +/* +К серверу по RMI +*/ +public class Solution { + public static final String UNIC_BINDING_NAME = "double.string"; + public static Registry registry; + + //pretend we start rmi client as CLIENT_THREAD thread + public static Thread CLIENT_THREAD = new Thread(new Runnable() { + @Override + public void run() { + try { + DoubleString clientService = (DoubleString) registry.lookup(UNIC_BINDING_NAME); + System.out.println(clientService.doubleString("Hello")); + + } catch (RemoteException e) { + e.printStackTrace(); + } catch (NotBoundException e) { + e.printStackTrace(); + } + //напишите тут ваш код + } + }); + + public static void main(String[] args) { + //pretend we start rmi server as main thread + Remote stub = null; + try { + registry = LocateRegistry.createRegistry(2099); + final DoubleStringImpl service = new DoubleStringImpl(); + + stub = UnicastRemoteObject.exportObject(service, 0); + registry.bind(UNIC_BINDING_NAME, stub); + } catch (RemoteException e) { + e.printStackTrace(); + } catch (AlreadyBoundException e) { + e.printStackTrace(); + } + + //start client + CLIENT_THREAD.start(); + } +} \ No newline at end of file diff --git "a/4.JavaCollections/src/com/javarush/task/task32/task3207/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task32/task3207/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..4c560c5 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task32/task3207/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,20 @@ +taskKey="com.javarush.task.task32.task3207" + +К серверу по RMI + +Реализуй логику метода run в CLIENT_THREAD. В нем будет имитироваться клиентская часть, которая коннектится к серверу. +1) Из registry получи сервис с именем UNIC_BINDING_NAME. +2) Вызови метод у полученного сервиса, передай любой не пустой аргумент. +3) Выведи в консоль результат вызова метода. +4) Обработай специфические исключения. +Метод main не участвует в тестировании. + + +Требования: +1. В методе run() необходимо из registry получить сервис с именем UNIC_BINDING_NAME. +2. В методе run() необходимо вызвать метод doubleString (String) у полученного сервиса. +3. В методе run() необходимо вывести в консоль результат вызова метода doubleString (String). +4. В методе run() должен быть перехват исключения RemoteException. +5. В методе run() должен быть перехват исключения NotBoundException. + + diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3208/Animal.java b/4.JavaCollections/src/com/javarush/task/task32/task3208/Animal.java new file mode 100644 index 0000000..ff03598 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3208/Animal.java @@ -0,0 +1,11 @@ +package com.javarush.task.task32.task3208; + +import java.rmi.Remote; +import java.rmi.RemoteException; + +public interface Animal extends Remote { + void say() throws RemoteException; + + void printName() throws RemoteException; +} + diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3208/Cat.java b/4.JavaCollections/src/com/javarush/task/task32/task3208/Cat.java new file mode 100644 index 0000000..1209248 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3208/Cat.java @@ -0,0 +1,22 @@ +package com.javarush.task.task32.task3208; + +import java.rmi.RemoteException; + +public class Cat implements Animal { + + private String name; + + public Cat(String name) { + this.name = name; + } + + @Override + public void say() throws RemoteException { + System.out.println("meow"); + } + + @Override + public void printName() throws RemoteException { + System.out.print("Cat " + name + " "); + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3208/Dog.java b/4.JavaCollections/src/com/javarush/task/task32/task3208/Dog.java new file mode 100644 index 0000000..95ae059 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3208/Dog.java @@ -0,0 +1,22 @@ +package com.javarush.task.task32.task3208; + +import java.rmi.RemoteException; + +public class Dog implements Animal { + + private String name; + + public Dog(String name) { + this.name = name; + } + + @Override + public void say() throws RemoteException { + System.out.println("woof"); + } + + @Override + public void printName() throws RemoteException { + System.out.print("Dog " + name + " "); + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3208/Solution.java b/4.JavaCollections/src/com/javarush/task/task32/task3208/Solution.java new file mode 100644 index 0000000..94566cf --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3208/Solution.java @@ -0,0 +1,64 @@ +package com.javarush.task.task32.task3208; + +import java.rmi.AlreadyBoundException; +import java.rmi.NotBoundException; +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +import java.rmi.server.UnicastRemoteObject; + +/* +RMI-2 +*/ +public class Solution { + public static Registry registry; + + //pretend we start rmi client as CLIENT_THREAD thread + public static Thread CLIENT_THREAD = new Thread(new Runnable() { + @Override + public void run() { + try { + for (String bindingName : registry.list()) { + Animal service = (Animal) registry.lookup(bindingName); + service.printName(); + service.say(); + } + } catch (RemoteException e) { + e.printStackTrace(); + } catch (NotBoundException e) { + e.printStackTrace(); + } + } + }); + + //pretend we start rmi server as SERVER_THREAD thread + public static Thread SERVER_THREAD = new Thread(new Runnable() { + @Override + public void run() { + Remote stub = null; + try { + registry = LocateRegistry.createRegistry(2099); + Cat catService = new Cat("Cat"); + Dog dogService = new Dog("Dog"); + stub = UnicastRemoteObject.exportObject(catService, 0); + registry.bind("CAT_NAME", stub); + stub = UnicastRemoteObject.exportObject(dogService, 0); + registry.bind("DOG_NAME", stub); + } catch (RemoteException e){ + e.printStackTrace(); + } catch (AlreadyBoundException e) { + e.printStackTrace(); + } + //напишите тут ваш код + } + }); + + public static void main(String[] args) throws InterruptedException { + //start rmi server thread + SERVER_THREAD.start(); + Thread.sleep(1000); + //start client + CLIENT_THREAD.start(); + } +} \ No newline at end of file diff --git "a/4.JavaCollections/src/com/javarush/task/task32/task3208/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task32/task3208/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..1094864 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task32/task3208/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,22 @@ +taskKey="com.javarush.task.task32.task3208" + +RMI-2 + +Реализуй логику метода run в SERVER_THREAD. В нем будет имитироваться серверная часть: +1) Инициализируй поле registry, которое будет принимать и обрабатывать запросы на 2099 порту. +2) Создай два объекта - Cat и Dog. +3) Используй класс UnicastRemoteObject, чтобы создать Remote объекты для созданных Cat и Dog. +Remote объекты будут в состоянии принимать обращения к своим методам используя выбранный порт (2099). +4) Для Cat и Dog добавь в registry связь уникального текстового ключа и Remote объекта. Текстовый ключ придумай сам. +5) При возникновении любого исключения выведи его стек-трейс в поток System.err. +Метод main не участвует в тестировании. + + +Требования: +1. В методе run() необходимо инициализировать поле registry. Для этого используй LocateRegistry.createRegistry (2099). +2. В методе run() необходимо создать два объекта - Cat и Dog. +3. В методе run() необходимо создать Remote объекты для созданных Cat и Dog используя UnicastRemoteObject.exportObject (Remote, int). +4. Для Cat и Dog нужно добавить в registry связь уникального текстового ключа и Remote объекта используя registry.bind (String, Remote). +5. При возникновении любого исключения нужно вывести его стек-трейс в поток System.err используя метод printStackTrace (). + + diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3210/Solution.java b/4.JavaCollections/src/com/javarush/task/task32/task3210/Solution.java new file mode 100644 index 0000000..c3a17fc --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3210/Solution.java @@ -0,0 +1,36 @@ +package com.javarush.task.task32.task3210; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/* +Используем RandomAccessFile +*/ + +public class Solution { + public static void main(String... args) { + if (args[0] == null || args[1] == null || args[2] == null) { return; } + try ( RandomAccessFile raf = new RandomAccessFile(args[0], "rw"); + ) { + byte[] buffer = new byte[args[2].length()]; + raf.seek(Integer.parseInt(args[1])); + long length = 0; + if ( (length = (raf.length() - Integer.parseInt(args[1]))) > buffer.length ) { + raf.read(buffer, 0, buffer.length); + } else { + raf.read(buffer, 0, (int) length); + } + raf.seek(raf.length()); + if (args[2].equals(convertByteToString(buffer))){ + raf.write("true".getBytes()); + }else { + raf.write("false".getBytes()); + } + } catch (IOException e) { + } + } + + public static String convertByteToString(byte[] readBytes){ + return new String(readBytes); + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task32/task3210/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task32/task3210/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..c56579d --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task32/task3210/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,24 @@ +taskKey="com.javarush.task.task32.task3210" + +Используем RandomAccessFile + +В метод main приходят три параметра: +1) fileName - путь к файлу; +2) number - число, позиция в файле; +3) text - текст. + +Считать текст с файла начиная с позиции number, длинной такой же как и длинна переданного текста в третьем параметре. +Если считанный текст такой же как и text, то записать в конец файла строку 'true', иначе записать 'false'. +Используй RandomAccessFile и его методы seek(long pos), read(byte b[], int off, int len), write(byte b[]). +Используй convertByteToString(byte readBytes[]) для конвертации считанной строчки в текст. + + +Требования: +1. В методе main класса Solution необходимо использовать RandomAccessFile, который должен использовать файл, который приходит первым параметром. +2. В методе main класса Solution программа должна устанавливать позицию в файле, которая передана во втором параметре. +3. В методе main класса Solution программа должна считывать данные с файла при помощи метода read(byte b[], int off, int len). +4. Запись должна происходить в конец файла. +5. Если считанный текст такой же как и text, то программа должна записать в конец переданного файла строку 'true'. +6. Если считанный текст НЕ такой же как и text, то программа должна записать в конец переданного файла строку 'false'. + + diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3211/Solution.java b/4.JavaCollections/src/com/javarush/task/task32/task3211/Solution.java new file mode 100644 index 0000000..1f07d9a --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3211/Solution.java @@ -0,0 +1,39 @@ +package com.javarush.task.task32.task3211; + +import java.io.ByteArrayOutputStream; +import java.io.ObjectOutputStream; +import java.security.MessageDigest; +import java.util.Arrays; + +/* +Целостность информации +*/ + +public class Solution { + public static void main(String... args) throws Exception { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(new String("test string")); + oos.flush(); + System.out.println(compareMD5(bos, "5a47d12a2e3f9fecf2d9ba1fd98152eb")); //true + + } + + public static boolean compareMD5(ByteArrayOutputStream byteArrayOutputStream, String md5) throws Exception { + if (byteArrayOutputStream != null){ + MessageDigest messageDigest = MessageDigest.getInstance("MD5"); + messageDigest.update(byteArrayOutputStream.toByteArray()); + byte[] md = messageDigest.digest(); + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < md.length; i++){ + String s = Integer.toHexString(0xff & md[i]); + s = (s.length() == 1) ? "0" + s : s; + sb.append(s); + } + if (md5.equals(sb.toString())) { return true; } + else { return false; } + } + + return false; + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task32/task3211/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task32/task3211/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..cd26c3e --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task32/task3211/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,20 @@ +taskKey="com.javarush.task.task32.task3211" + +Целостность информации + +Представь ситуацию, ты выкачал архив с интернета, и в момент скачивания у тебя на несколько секунд пропало соединение. +Нужно убедиться, валидный ли архив ты скачал. Для этого сверим его MD5 хеш. +Прочитать о MD5 на wiki. +Прочитать о MessageDigest. + +Реализуй логику метода compareMD5, который должен получать MD5 хеш из переданного ByteArrayOutputStream и сравнивать с эталонным MD5 переданным вторым параметром. +Метод main не участвует в тестировании. + + +Требования: +1. Класс Solution должен содержать метод compareMD5(ByteArrayOutputStream byteArrayOutputStream, String md5). +2. Метод compareMD5(ByteArrayOutputStream byteArrayOutputStream, String md5) должен использовать MessageDigest. +3. Метод compareMD5(ByteArrayOutputStream byteArrayOutputStream, String md5) должен возвращать результат сравнения вычисленного MD5 хеша для byteArrayOutputStream с переданным параметром md5. +4. Класс Solution должен содержать метод main. + + diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3212/Cache.java b/4.JavaCollections/src/com/javarush/task/task32/task3212/Cache.java new file mode 100644 index 0000000..9d0537b --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3212/Cache.java @@ -0,0 +1,36 @@ +package com.javarush.task.task32.task3212; + +import com.javarush.task.task32.task3212.service.Service; + +import java.util.ArrayList; +import java.util.List; + +public class Cache { + private List services; + + public Cache() { + services = new ArrayList<>(); + } + + public Service getService(String serviceName) { + for (Service service : services) { + if (service.getName().equalsIgnoreCase(serviceName)) { + System.out.println("Return cached " + serviceName + " object"); + return service; + } + } + return null; + } + + public void addService(Service newService) { + boolean exists = false; + for (Service service : services) { + if (service.getName().equalsIgnoreCase(newService.getName())) { + exists = true; + } + } + if (!exists) { + services.add(newService); + } + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3212/ServiceLocator.java b/4.JavaCollections/src/com/javarush/task/task32/task3212/ServiceLocator.java new file mode 100644 index 0000000..b189022 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3212/ServiceLocator.java @@ -0,0 +1,32 @@ +package com.javarush.task.task32.task3212; + +import com.javarush.task.task32.task3212.contex.InitialContext; +import com.javarush.task.task32.task3212.service.Service; + + + +public class ServiceLocator { + private static Cache cache; + + static { + cache = new Cache(); + } + + /** + * First check the service object available in cache + * If service object not available in cache do the lookup using + * JNDI initial context and get the service object. Add it to + * the cache for future use. + * + * @param jndiName The name of service object in context + * @return Object mapped to name in context + */ + public static Service getService(String jndiName) { + Service service = cache.getService(jndiName); + if (service == null) { + service = (Service) new InitialContext().lookup(jndiName); + cache.addService(service); + } + return service; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3212/Solution.java b/4.JavaCollections/src/com/javarush/task/task32/task3212/Solution.java new file mode 100644 index 0000000..7c4dc37 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3212/Solution.java @@ -0,0 +1,25 @@ +package com.javarush.task.task32.task3212; + +import com.javarush.task.task32.task3212.service.Service; + +/* +Service Locator +*/ + +public class Solution { + public static void main(String[] args) { + Service service = ServiceLocator.getService("EJBService"); + service.execute(); + System.out.println(); + service = ServiceLocator.getService("JMSService"); + service.execute(); + System.out.println(); + service = ServiceLocator.getService("EJBService"); + service.execute(); + System.out.println(); + service = ServiceLocator.getService("JMSService"); + service.execute(); + + } + +} diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3212/contex/InitialContext.java b/4.JavaCollections/src/com/javarush/task/task32/task3212/contex/InitialContext.java new file mode 100644 index 0000000..a6c75a9 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3212/contex/InitialContext.java @@ -0,0 +1,18 @@ +package com.javarush.task.task32.task3212.contex; + +import com.javarush.task.task32.task3212.service.impl.EJBServiceImpl; +import com.javarush.task.task32.task3212.service.impl.JMSServiceImpl; + +public class InitialContext { + public Object lookup(String jndiName) { + + if (jndiName.equalsIgnoreCase("EJBService")) { + System.out.println("Looking up and creating a new EJBService object"); + return new EJBServiceImpl(); + } else if (jndiName.equalsIgnoreCase("JMSService")) { + System.out.println("Looking up and creating a new JMSService object"); + return new JMSServiceImpl(); + } + return null; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3212/service/Service.java b/4.JavaCollections/src/com/javarush/task/task32/task3212/service/Service.java new file mode 100644 index 0000000..4dba150 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3212/service/Service.java @@ -0,0 +1,7 @@ +package com.javarush.task.task32.task3212.service; + +public interface Service { + String getName(); + + void execute(); +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3212/service/impl/EJBServiceImpl.java b/4.JavaCollections/src/com/javarush/task/task32/task3212/service/impl/EJBServiceImpl.java new file mode 100644 index 0000000..5f6f65f --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3212/service/impl/EJBServiceImpl.java @@ -0,0 +1,17 @@ +package com.javarush.task.task32.task3212.service.impl; + +import com.javarush.task.task32.task3212.service.Service; + +public class EJBServiceImpl implements Service { + + @Override + public void execute() { + System.out.println("Executing EJBService"); + } + + @Override + public String getName() { + return "EJBService"; + } + +} diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3212/service/impl/JMSServiceImpl.java b/4.JavaCollections/src/com/javarush/task/task32/task3212/service/impl/JMSServiceImpl.java new file mode 100644 index 0000000..a9169e6 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3212/service/impl/JMSServiceImpl.java @@ -0,0 +1,17 @@ +package com.javarush.task.task32.task3212.service.impl; + +import com.javarush.task.task32.task3212.service.Service; + +public class JMSServiceImpl implements Service { + + @Override + public void execute() { + System.out.println("Executing JMSService"); + } + + @Override + public String getName() { + return "JMSService"; + } + +} diff --git "a/4.JavaCollections/src/com/javarush/task/task32/task3212/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task32/task3212/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..d4ea661 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task32/task3212/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,24 @@ +taskKey="com.javarush.task.task32.task3212" + +Service Locator + +Прочитать о паттерне Service locator. + +Реализуй логику метода getService(String jndiName) в ServiceLocator. +В нем будет реализована работа с контекстом и кэшем. + +1) Верни из кэша нужный сервис. +2) Если в кэше нет нужного сервиса то: +2.1) Создай контекст. +2.2) Возьми у контекста нужный сервис. +2.3) Добавь сервис в кеш и верни его. + + +Требования: +1. Класс ServiceLocator должен содержать метод Service getService(String jndiName). +2. Если нужный сервис находится в кэше, метод getService(String jndiName) должен возвращать сервис из кэша. +3. Если нужный сервис НЕ находится в кэше, метод getService(String jndiName) должен создавать контекст. +4. Если нужный сервис НЕ находится в кэше, метод getService(String jndiName) должен искать нужный сервис в контексте. +5. Если нужный сервис НЕ находится в кэше, метод getService(String jndiName) должен добавлять в кэш сервис, найденный в контексте и возвращать его. + + diff --git a/4.JavaCollections/src/com/javarush/task/task32/task3213/Solution.java b/4.JavaCollections/src/com/javarush/task/task32/task3213/Solution.java new file mode 100644 index 0000000..3c4994f --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task32/task3213/Solution.java @@ -0,0 +1,28 @@ +package com.javarush.task.task32.task3213; + +import java.io.IOException; +import java.io.StringReader; + +/* +Шифр Цезаря +*/ + +public class Solution { + public static void main(String[] args) throws IOException { + StringReader reader = new StringReader("Khoor Dpljr"); + System.out.println(decode(reader, -3)); //Hello Amigo + + } + + public static String decode(StringReader reader, int key) throws IOException { + StringBuilder builder = new StringBuilder(); + int symbol = 0; + if (reader != null) { + while ((symbol = reader.read()) != -1) { + builder.append((char) (symbol + key)); + } + } + return builder.toString(); + } + +} diff --git "a/4.JavaCollections/src/com/javarush/task/task32/task3213/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task32/task3213/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..4e441ff --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task32/task3213/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,21 @@ +taskKey="com.javarush.task.task32.task3213" + +Шифр Цезаря + +Привет Амиго. Ты знаешь, за нами следят, просматривают нашу переписку. Поэтому нужно шифровать трафик. +Для тебя не составит труда реализовать шифр Цезаря, напомню что это просто сдвиг вправо по алфавиту на key букв. +В методе main есть хороший пример. + +Реализуй логику метода String decode(StringReader reader, int key). +Метод получает данные в закодированном виде. +Он должен вернуть дешифрованную строку, что хранится в StringReader - е. +Возвращаемый объект ни при каких условиях не должен быть null. +Метод main не участвует в тестировании. + + +Требования: +1. Класс Solution должен содержать метод String decode(StringReader reader, int key). +2. Метод decode(StringReader reader, int key) должен вернуть дешифрованную строку что хранится в StringReader - е. +3. Возвращаемый объект ни при каких условиях не должен быть null. + + diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3301/Solution.java b/4.JavaCollections/src/com/javarush/task/task33/task3301/Solution.java new file mode 100644 index 0000000..ce2bdf5 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3301/Solution.java @@ -0,0 +1,76 @@ +package com.javarush.task.task33.task3301; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.ArrayList; + +/* +Первая сериализация в JSON +*/ +public class Solution { + public static void main(String[] args) throws IOException { + Cat cat = new Cat(); + cat.name = "Murka"; + cat.age = 5; + cat.weight = 3; + + Dog dog = new Dog(); + dog.name = "Killer"; + dog.age = 8; + dog.owner = "Bill Jeferson"; + + ArrayList pets = new ArrayList<>(); + pets.add(cat); + pets.add(dog); + + StringWriter writer = new StringWriter(); + convertToJSON(writer, pets); + System.out.println(writer.toString()); + //[{"name":"Murka","age":5,"weight":3},{"name":"Killer","age":8,"owner":"Bill Jeferson"}] + } + + public static void convertToJSON(StringWriter writer, Object object) throws IOException { + ObjectMapper mapper = new ObjectMapper(); + mapper.writeValue(writer, object); + } + + @JsonAutoDetect + public static class Pet { + String name; + + public String getName() { + return name; + } + } + + @JsonAutoDetect + public static class Cat extends Pet { + int age; + int weight; + + public int getAge() { + return age; + } + + public int getWeight() { + return weight; + } + } + + @JsonAutoDetect + public static class Dog extends Pet { + int age; + String owner; + + public int getAge() { + return age; + } + + public String getOwner() { + return owner; + } + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task33/task3301/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task33/task3301/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..3d9603c --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task33/task3301/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,19 @@ +taskKey="com.javarush.task.task33.task3301" + +Первая сериализация в JSON + +НЕОБХОДИМО: подключенные библиотеки Jackson Core, Bind и Annotation версии 2.6.1 + +1) В программе не выполнено основное требование к сериализации в JSON. +Найди ошибку и исправь. +2) Расставь правильно JSON аннотации у классов. +Все данные должны сериализоваться. + + +Требования: +1. Класс Pet должен быть помечен как готовый к сериализации в JSON. +2. Класс Cat должен быть помечен как готовый к сериализации в JSON. +3. Класс Dog должен быть помечен как готовый к сериализации в JSON. +4. Все данные у классов Pet, Cat, Dog должны сериализоваться. + + diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3302/Solution.java b/4.JavaCollections/src/com/javarush/task/task33/task3302/Solution.java new file mode 100644 index 0000000..4f6c9d7 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3302/Solution.java @@ -0,0 +1,44 @@ +package com.javarush.task.task33.task3302; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; +import java.io.StringWriter; + +/* +Вторая сериализация в JSON +*/ +public class Solution { + public static void main(String[] args) throws IOException { + Cat cat = new Cat(); + cat.name = "Murka"; + cat.age = 5; + cat.weight = 3; + + StringWriter writer = new StringWriter(); + convertToJSON(writer, cat); + System.out.println(writer.toString()); + } + + public static void convertToJSON(StringWriter writer, Object object) throws IOException { + ObjectMapper mapper = new ObjectMapper(); + mapper.writeValue(writer, object); + } + + @JsonAutoDetect + public static class Cat { + @JsonProperty("wildAnimal") public String name; + + @JsonIgnore public int age; + + @JsonProperty("over") + public int weight; + + Cat() { + } + } + +} diff --git "a/4.JavaCollections/src/com/javarush/task/task33/task3302/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task33/task3302/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..db628a2 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task33/task3302/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,18 @@ +taskKey="com.javarush.task.task33.task3302" + +Вторая сериализация в JSON + +НЕОБХОДИМО: подключенные библиотеки Jackson Core, Bind и Annotation версии 2.6.1 + +Расставь JSON аннотации так, чтобы результат работы метода main был следующим +{"wildAnimal":"Murka","over":3} + + +Требования: +1. Поле name класса Cat должно быть отмечено аннотацией JsonProperty. +2. Поле age класса Cat должно быть отмечено аннотацией JsonIgnore. +3. Поле weight класса Cat должно быть отмечено аннотацией JsonProperty. +4. Значение (value) аннотации JsonProperty у поля name должно быть равно "wildAnimal". +5. Значение (value) аннотации JsonProperty у поля weight должно быть равно "over". + + diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3303/Solution.java b/4.JavaCollections/src/com/javarush/task/task33/task3303/Solution.java new file mode 100644 index 0000000..366f8dd --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3303/Solution.java @@ -0,0 +1,21 @@ +package com.javarush.task.task33.task3303; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.File; +import java.io.IOException; + +/* +Десериализация JSON объекта +*/ +public class Solution { + public static T convertFromJsonToNormal(String fileName, Class clazz) throws IOException { + ObjectMapper mapper = new ObjectMapper(); + T returnObject = mapper.readValue(new File(fileName), clazz); + return returnObject; + } + + public static void main(String[] args) { + + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task33/task3303/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task33/task3303/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..3fc88dc --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task33/task3303/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,18 @@ +taskKey="com.javarush.task.task33.task3303" + +Десериализация JSON объекта + +НЕОБХОДИМО: подключенные библиотеки Jackson Core, Bind и Annotation версии 2.6.1 + +В метод convertFromJsonToNormal первым параметром приходит имя файла, который содержит один ДЖЕЙСОН объект. +Вторым параметром приходит имя класса, объект которого находится в файле. +Метод convertFromJsonToNormal должен вычитать объект из файла, преобразовать его из JSON и вернуть. + + +Требования: +1. В методе convertFromJsonToNormal должен быть создан объект типа ObjectMapper с помощью конструктора без параметров. +2. Объект возвращаемый методом convertFromJsonToNormal должен быть получен с помощью метода readValue класса ObjectMapper. +3. Метод convertFromJsonToNormal должен быть статическим. +4. Метод convertFromJsonToNormal должен быть публичным. + + diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3304/Solution.java b/4.JavaCollections/src/com/javarush/task/task33/task3304/Solution.java new file mode 100644 index 0000000..308c1e5 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3304/Solution.java @@ -0,0 +1,46 @@ +package com.javarush.task.task33.task3304; + +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.lang.annotation.Annotation; + +/* +Конвертация из одного класса в другой используя JSON +*/ +public class Solution { + public static void main(String[] args) throws IOException { + Second s = (Second) convertOneToAnother(new First(), Second.class); + First f = (First) convertOneToAnother(new Second(), First.class); + } + + public static Object convertOneToAnother(Object one, Class resultClassObject) throws IOException { + ObjectMapper mapper = new ObjectMapper(); + StringWriter writer = new StringWriter(); + mapper.writeValue(writer, one); + + String outString = writer.toString().replaceFirst(one.getClass().getSimpleName().toLowerCase(), resultClassObject.getSimpleName().toLowerCase()); + return mapper.readValue(outString, resultClassObject); + } + + @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property="className") + @JsonSubTypes(@JsonSubTypes.Type(value=First.class, name="first")) + public static class First { + public int i; + public String name; + } + + @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property="className") + @JsonSubTypes(@JsonSubTypes.Type(value=Second.class, name="second")) + public static class Second { + public int i; + public String name; + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task33/task3304/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task33/task3304/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..d3d43ca --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task33/task3304/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,22 @@ +taskKey="com.javarush.task.task33.task3304" + +Конвертация из одного класса в другой используя JSON + +НЕОБХОДИМО: подключенные библиотеки Jackson Core, Bind и Annotation версии 2.6.1 + +Два класса имеют одинаковые поля, но не имеют общий суперкласс. Пример, классы First и Second. +Реализовать логику метода convertOneToAnother, который должен возвращать объект класса resultClassObject, +значения полей которого равны значениям полей в объекте one. +Используй объект типа ObjectMapper. +Известно, что у классов есть JSON аннотация, у которой значение property равно имени класса в нижнем регистре. +На примере класса First, это className="first" +Классы First и Second не участвуют в тестировании, они предоставлены в качестве тестовых данных. + + +Требования: +1. Метод convertOneToAnother должен возвращать объект класса resultClassObject значения полей которого равны значениям полей объекта one. +2. В методе convertOneToAnother должен быть создан объект типа ObjectMapper. +3. Метод convertOneToAnother должен быть статическим. +4. Метод convertOneToAnother должен быть публичным. + + diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3305/Auto.java b/4.JavaCollections/src/com/javarush/task/task33/task3305/Auto.java new file mode 100644 index 0000000..885a28a --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3305/Auto.java @@ -0,0 +1,14 @@ +package com.javarush.task.task33.task3305; + +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; + +@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "className" ) +@JsonSubTypes({ @JsonSubTypes.Type(value = Car.class, name = "car"), + @JsonSubTypes.Type(value = Motorbike.class, name = "motorbike"), + @JsonSubTypes.Type(value = RaceBike.class, name = "race-bike")}) +public abstract class Auto { + protected String name; + protected String owner; + protected int age; +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3305/Car.java b/4.JavaCollections/src/com/javarush/task/task33/task3305/Car.java new file mode 100644 index 0000000..b740f1b --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3305/Car.java @@ -0,0 +1,4 @@ +package com.javarush.task.task33.task3305; + +public class Car extends Auto { +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3305/Motorbike.java b/4.JavaCollections/src/com/javarush/task/task33/task3305/Motorbike.java new file mode 100644 index 0000000..630a237 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3305/Motorbike.java @@ -0,0 +1,29 @@ +package com.javarush.task.task33.task3305; + +public class Motorbike extends Auto { + private String owner; + + public Motorbike(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + this.owner = owner; + } + + @Override + public String toString() { + return "Motorbike{" + + "name='" + name + '\'' + + ", owner='" + owner + '\'' + + '}'; + } +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3305/Parking.java b/4.JavaCollections/src/com/javarush/task/task33/task3305/Parking.java new file mode 100644 index 0000000..d54cf3a --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3305/Parking.java @@ -0,0 +1,31 @@ +package com.javarush.task.task33.task3305; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonTypeInfo; + +import java.util.List; + +//@JsonTypeInfo(use = JsonTypeInfo.Id.MINIMAL_CLASS, property = "className" ) +public class Parking { + public String name; + public String city; + public List autos; + + public Parking(String name, String city) { + this.name = name; + this.city = city; + } + + public void setAutos(List autos) { + this.autos = autos; + } + + @Override + public String toString() { + return "Parking{" + + "name='" + name + '\'' + + ", city='" + city + '\'' + + ", autos=" + autos + + '}'; + } +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3305/RaceBike.java b/4.JavaCollections/src/com/javarush/task/task33/task3305/RaceBike.java new file mode 100644 index 0000000..0ff3d34 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3305/RaceBike.java @@ -0,0 +1,33 @@ +package com.javarush.task.task33.task3305; + +public class RaceBike extends Motorbike { + private String owner; + private int age; + + public RaceBike(String name, String owner, int age) { + super(name); + this.owner = owner; + this.age = age; + } + + public String getName() { + return name; + } + + public String getOwner() { + return owner; + } + + public int getAge() { + return age; + } + + @Override + public String toString() { + return "RaceBike{" + + "name='" + name + '\'' + + ", owner='" + owner + '\'' + + ", age=" + age + + '}'; + } +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3305/Solution.java b/4.JavaCollections/src/com/javarush/task/task33/task3305/Solution.java new file mode 100644 index 0000000..24dc392 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3305/Solution.java @@ -0,0 +1,33 @@ +package com.javarush.task.task33.task3305; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.List; + +/* +Конвертация из одного класса в другой используя JSON +*/ +public class Solution { + public static void main(String[] args) throws IOException { + Parking parking = new Parking("Super Parking", "Kyiv"); + RaceBike raceBike = new RaceBike("Simba", "Peter", 2); + Motorbike motorbike = new Motorbike("Manny"); + Car car = new Car(); + List autos = new ArrayList<>(); + autos.add(raceBike); + autos.add(motorbike); + autos.add(car); + parking.setAutos(autos); + convertToJson(parking); + } + + public static void convertToJson(Parking parking) throws IOException { + StringWriter writer = new StringWriter(); + ObjectMapper mapper = new ObjectMapper(); + mapper.writerWithDefaultPrettyPrinter().writeValue(writer, parking); + System.out.println(writer.toString()); + } +} \ No newline at end of file diff --git "a/4.JavaCollections/src/com/javarush/task/task33/task3305/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task33/task3305/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..93ce0d2 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task33/task3305/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,35 @@ +taskKey="com.javarush.task.task33.task3305" + +Конвертация из одного класса в другой используя JSON + +НЕОБХОДИМО: подключенные библиотеки Jackson Core, Bind и Annotation версии 2.6.1 + +Расставь JSON аннотации так, чтобы результат выполнения метода main был следующим: +{ +"className" : ".Parking", +"name" : "Super Parking", +"city" : "Kyiv", +"autos" : [ { +"className" : "com.javarush.task.task33.task3305.RaceBike", +"name" : "Simba", +"owner" : "Peter", +"age" : 2 +}, { +"className" : "com.javarush.task.task33.task3305.Motorbike", +"name" : "Manny", +"owner" : null +}, { +"className" : "com.javarush.task.task33.task3305.Car" +} ] +} + +Подсказка: это всего два класса. + + +Требования: +1. Вывод на экран должен соответствовать условию задачи. +2. Класс Parking должен быть отмечен аннотацией @JsonTypeInfo с подходящим набором параметров. +3. Класс Auto должен быть отмечен аннотацией @JsonTypeInfo с подходящим набором параметров. +4. Класс Auto должен быть отмечен аннотацией @JsonSubTypes с подходящим набором параметров. + + diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3306/Solution.java b/4.JavaCollections/src/com/javarush/task/task33/task3306/Solution.java new file mode 100644 index 0000000..4295ad0 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3306/Solution.java @@ -0,0 +1,70 @@ +package com.javarush.task.task33.task3306; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; +import java.io.IOException; +import java.io.StringWriter; + +/* +Первая сериализация в XML +*/ +public class Solution { + public static void main(String[] args) throws IOException, JAXBException { + Cat cat = new Cat(); + cat.name = "Murka"; + cat.age = 5; + cat.weight = 3; + + Dog dog = new Dog(); + dog.name = "Killer"; + dog.age = 8; + dog.owner = "Bill Jeferson"; + + StringWriter writer = new StringWriter(); + convertToXml(writer, cat); + convertToXml(writer, dog); + System.out.println(writer.toString()); + /* expected output + + + Murka + 5 + 3 + + + + Killer + 8 + Bill Jeferson + + */ + } + + public static void convertToXml(StringWriter writer, Object obj) throws IOException, JAXBException { + JAXBContext context = JAXBContext.newInstance(obj.getClass()); + Marshaller marshaller = context.createMarshaller(); + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); + marshaller.marshal(obj, writer); + } + + public static class Pet { + public String name; + } + + @XmlType(name = "cat") + @XmlRootElement + public static class Cat extends Pet { + public int age; + public int weight; + } + + @XmlType(name = "dog") + @XmlRootElement + public static class Dog extends Pet { + public int age; + public String owner; + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task33/task3306/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task33/task3306/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..c586af3 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task33/task3306/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,14 @@ +taskKey="com.javarush.task.task33.task3306" + +Первая сериализация в XML + +Расставь правильно JAXB аннотации у статических классов. + + +Требования: +1. Класс Cat должен быть отмечен аннотацией @XmlRootElement. +2. Класс Cat должен быть отмечен аннотацией @XmlType с параметром name = "cat". +3. Класс Dog должен быть отмечен аннотацией @XmlRootElement. +4. Класс Dog должен быть отмечен аннотацией @XmlType с параметром name = "dog". + + diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3307/Solution.java b/4.JavaCollections/src/com/javarush/task/task33/task3307/Solution.java new file mode 100644 index 0000000..d69fff6 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3307/Solution.java @@ -0,0 +1,45 @@ +package com.javarush.task.task33.task3307; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; +import java.io.IOException; +import java.io.StringReader; + +/* +Десериализация XML объекта +*/ +public class Solution { + public static void main(String[] args) throws IOException, JAXBException { + String xmlData = "Murka54"; + Cat cat = convertFromXmlToNormal(xmlData, Cat.class); + System.out.println(cat); + } + + public static T convertFromXmlToNormal(String xmlData, Class clazz) throws IOException, JAXBException { + JAXBContext context = JAXBContext.newInstance(clazz); + Unmarshaller unmarshaller = context.createUnmarshaller(); + StringReader reader = new StringReader(xmlData); + return (T) unmarshaller.unmarshal(reader); + } + + @XmlType(name = "cat") + @XmlRootElement + public static class Cat { + public String name; + public int age; + public int weight; + + @Override + public String toString() { + return "Cat{" + + "name='" + name + '\'' + + ", age=" + age + + ", weight=" + weight + + '}'; + } + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task33/task3307/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task33/task3307/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..8dc4636 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task33/task3307/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,16 @@ +taskKey="com.javarush.task.task33.task3307" + +Десериализация XML объекта + +В метод convertFromXmlToNormal первым параметром приходит строка, содержащая xml объект. +Вторым параметром приходит класс, объект которого необходимо вернуть. +Метод convertFromXmlToNormal должен создать объект из xml-строки и вернуть его. + + +Требования: +1. В методе convertFromXmlToNormal должен быть создан новый объект типа JAXBContext с помощью статического метода JAXBContext.newInstance, в качестве параметра используй целевой класс. +2. В методе convertFromXmlToNormal должен быть создан новый объект типа Unmarshaller с помощью метода createUnmarshaller вызванного на объекте типа JAXBContext. +3. Метод convertFromXmlToNormal должен корректно преобразовывать входящую xml строку в объект требуемого класса. +4. Метод convertFromXmlToNormal должен быть статическим. + + diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3308/Shop.java b/4.JavaCollections/src/com/javarush/task/task33/task3308/Shop.java new file mode 100644 index 0000000..9c6de8b --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3308/Shop.java @@ -0,0 +1,23 @@ +package com.javarush.task.task33.task3308; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; +import java.util.List; + +/** + * Created by Archmage on 29.05.2017. + */ + +@XmlType(name = "shop") +@XmlRootElement +public class Shop { + public Goods goods; + public int count; + public double profit; + public String[] secretData; + + + public static class Goods{ + public List names; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3308/Solution.java b/4.JavaCollections/src/com/javarush/task/task33/task3308/Solution.java new file mode 100644 index 0000000..ec70db1 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3308/Solution.java @@ -0,0 +1,42 @@ +package com.javarush.task.task33.task3308; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import java.io.StringReader; + +/* +Создание класса по строке xml +*/ +public class Solution { + public static void main(String[] args) throws JAXBException { + String xmlData = + "\n" + + "\n" + + " \n" + + " S1\n" + + " S2\n" + + " \n" + + " 12\n" + + " 123.4\n" + + " String1\n" + + " String2\n" + + " String3\n" + + " String4\n" + + " String5\n" + + ""; + + StringReader reader = new StringReader(xmlData); + + JAXBContext context = JAXBContext.newInstance(getClassName()); + Unmarshaller unmarshaller = context.createUnmarshaller(); + + Object o = unmarshaller.unmarshal(reader); + + System.out.println(o.toString()); + } + + public static Class getClassName() { + return Shop.class; //your class name + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3308/data.xml b/4.JavaCollections/src/com/javarush/task/task33/task3308/data.xml new file mode 100644 index 0000000..f135b1a --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3308/data.xml @@ -0,0 +1,14 @@ + + + + S1 + S2 + + 12 + 123.4 + String1 + String2 + String3 + String4 + String5 + \ No newline at end of file diff --git "a/4.JavaCollections/src/com/javarush/task/task33/task3308/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task33/task3308/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..b4ef9a4 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task33/task3308/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,22 @@ +taskKey="com.javarush.task.task33.task3308" + +Создание класса по строке xml + +Восстанови класс по переданной строке xml. +Класс должен быть в отдельном файле. +Метод getClassName должен возвращать восстановленный класс. +Метод main не участвует в тестировании. + + +Требования: +1. Класс Shop должен быть создан в отдельном файле. +2. В классе Shop должно быть создано поле goods типа Goods. +3. В классе Shop должно быть создано поле count типа int. +4. В классе Shop должно быть создано поле profit типа double. +5. В классе Shop должен быть создан массив строк secretData. +6. В классе Shop должен содержаться вложенный статический класс Goods. +7. В классе Shop.Goods должен быть создан список строк names. +8. Все поля класса Shop должны быть публичными. +9. Метод getClassName класса Solution должен возвращать класс Shop. + + diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3309/Solution.java b/4.JavaCollections/src/com/javarush/task/task33/task3309/Solution.java new file mode 100644 index 0000000..fb59262 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3309/Solution.java @@ -0,0 +1,103 @@ +package com.javarush.task.task33.task3309; + + + +import org.w3c.dom.*; +import org.xml.sax.SAXException; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.*; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.IOException; +import java.io.StringWriter; + +/* +Комментарий внутри xml +*/ +public class Solution { + public static String toXmlWithComment(Object obj, String tagName, String comment) throws JAXBException, ParserConfigurationException, IOException, SAXException, TransformerException { + + JAXBContext context = JAXBContext.newInstance(obj.getClass()); + Marshaller marshaller = context.createMarshaller(); + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); + + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + Document doc = builder.newDocument(); + + StringWriter wr = new StringWriter(); + + marshaller.marshal(obj, doc); + NodeList nodes = doc.getElementsByTagName(tagName); + + //Element element = doc.getDocumentElement(); + Comment jcomment = null; + + createCdata(doc); + + for (int i = 0; i < nodes.getLength(); i++){ + jcomment = doc.createComment(comment); + /*nodes.item(i).getNodeType();*/ + nodes.item(i).getParentNode().insertBefore(jcomment ,nodes.item(i)); + } + /*for (int i = 0; i < nodes.getLength(); i++){ + *//*if (nodes.item(i).getNodeType() == Node.TEXT_NODE) {*//* + if (nodes.item(i).getTextContent().matches(".*[<>&'\"].*")){ + nodes.item(i).getParentNode().replaceChild(doc.createCDATASection(nodes.item(i).getTextContent()),nodes.item(i)); + } + *//*}*//* + //System.out.println(nodes.item(i).getTextContent()); + }*/ + + /*String xmlData = "\n" + + "\n" + + " name1\n" + + " name2 with second word\n" + + ""; + + Marshaller marshaller1 = JAXBContext.newInstance(String.class).createMarshaller(); + marshaller1.marshal(xmlData, doc);*/ + + + TransformerFactory tf = TransformerFactory.newInstance(); + Transformer t = tf.newTransformer(); + t.setOutputProperty(OutputKeys.INDENT, "yes"); + t.transform(new DOMSource(doc), new StreamResult(wr)); + + //marshaller.marshal(obj, wr); + return wr.toString(); + } + + private static void createCdata(Document doc){ + Node topNode = doc.getDocumentElement(); + Node currentNode = null; + for (currentNode = topNode.getFirstChild(); currentNode != null; currentNode = currentNode.getNextSibling()){ + if (currentNode.getTextContent().matches(".*[<>&'\"].*")) { + CDATASection cdata = doc.createCDATASection(currentNode.getTextContent()); + currentNode.replaceChild(cdata,currentNode.getFirstChild()); + /*Node parentNode = currentNode.getParentNode(); + parentNode.removeChild(currentNode); + parentNode.appendChild(cdata);*/ + //currentNode.getParentNode().replaceChild(doc.createCDATASection(currentNode.getTextContent()), currentNode); + } + } + } + + public static void main(String[] args) throws JAXBException, ParserConfigurationException, IOException, SAXException, TransformerException { + System.out.println(toXmlWithComment(new TestClass(), "needCDATA", "it's a comment - ")); + } + + @XmlType + @XmlRootElement(name = "first") + private static class TestClass { + public String[] needCDATA = new String[]{"some text1","some text 2", "need CDATA because of < and >", ""}; + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task33/task3309/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task33/task3309/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..a1715aa --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task33/task3309/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,31 @@ +taskKey="com.javarush.task.task33.task3309" + +Комментарий внутри xml + +Реализовать метод toXmlWithComment, который должен возвращать строку - xml представление объекта obj. +В строке перед каждым тегом tagName должен быть вставлен комментарий comment. +Сериализация obj в xml может содержать CDATA с искомым тегом. Перед ним вставлять комментарий не нужно. + +Пример вызова: toXmlWithComment(firstSecondObject, "second", "it's a comment") +Пример результата: + + + +some string + +some string + +]]> + + + + + +Требования: +1. Количество комментариев вставленных в xml должно быть равно количеству тегов tagName. +2. Метод toXmlWithComment должен возвращать xml в виде строки преобразованной в соответствии с условием задачи. +3. Метод toXmlWithComment не должен изменять входящий xml в случае, если искомый тег отсутствует в нём. +4. Метод toXmlWithComment должен быть статическим. +5. Метод toXmlWithComment должен быть публичным. + + diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3311/RealBean.java b/4.JavaCollections/src/com/javarush/task/task33/task3311/RealBean.java new file mode 100644 index 0000000..821c200 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3311/RealBean.java @@ -0,0 +1,40 @@ +package com.javarush.task.task33.task3311; + +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +import java.util.HashMap; +import java.util.Map; + +public class RealBean { + protected final int id; + protected final String name; + + protected Map additionalMap = new HashMap<>(); + + @JsonCreator + public RealBean(@JsonProperty("id") int id, @JsonProperty("name") String name) { + this.id = id; + this.name = name; + } + + public int getId() { + return id; + } + + public String getName() { + return name; + } + + + @JsonAnyGetter + public Map getAdditionalMap() { + return additionalMap; + } + + @JsonAnySetter + public void setAdditionalMap(String name, Object value) { + additionalMap.put(name, value); + } +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3311/Solution.java b/4.JavaCollections/src/com/javarush/task/task33/task3311/Solution.java new file mode 100644 index 0000000..8154d98 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3311/Solution.java @@ -0,0 +1,22 @@ +package com.javarush.task.task33.task3311; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; +import java.io.StringWriter; + +/* +Странная ошибка +*/ +public class Solution { + public static void main(String[] args) throws IOException { + StringWriter stringWriter = new StringWriter(); + ObjectMapper objectMapper = new ObjectMapper(); + /*String sampleJsonString = "{\"id\":1,\"name\":\"first\",\"additionalMap\":{\"KEY#1\":\"VALUE#1\",\"KEY#3\":\"VALUE#3\",\"KEY#2\":\"VALUE#2\"}}";*/ + String sampleJsonString = "{\"id\":1,\"name\":\"first\",\"KEY#1\":\"VALUE#1\",\"KEY#3\":\"VALUE#3\",\"KEY#2\":\"VALUE#2\"}"; + RealBean realBean = objectMapper.readValue(sampleJsonString, RealBean.class); + + objectMapper.writeValue(stringWriter, realBean); + System.out.println(stringWriter.toString()); + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task33/task3311/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task33/task3311/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..54f7496 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task33/task3311/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,20 @@ +taskKey="com.javarush.task.task33.task3311" + +Странная ошибка + +НЕОБХОДИМО: подключенные библиотеки Jackson Core, Bind и Annotation версии 2.6.1 + +В результате выполнения кода в методе main класса Solution возникает странная ошибка +при сериализации/десериализации в JSON. На экран должна быть выведена строка sampleJsonString, +а выводится не совсем она. + +Разберись в чем проблема и исправь. Обрати внимание на класс RealBean. + + +Требования: +1. Метод getAdditionalMap должен быть отмечен одной подходящей Jackson аннотацией. +2. Сериализация элементов additionalMap в json должна происходить, как сериализация обычных полей класса. +3. Десериализация элементов additionalMap из json должна происходить, как десериализация обычных полей класса. +4. Метод main должен выводить данные на экран. + + diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3312/Solution.java b/4.JavaCollections/src/com/javarush/task/task33/task3312/Solution.java new file mode 100644 index 0000000..69bd030 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3312/Solution.java @@ -0,0 +1,21 @@ +package com.javarush.task.task33.task3312; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +/* +Сериализация зоопарка +*/ +public class Solution { + public static void main(String[] args) throws JsonProcessingException { + Zoo.Dog dog = new Zoo.Dog("doggy"); + Zoo.Cat cat = new Zoo.Cat("catty"); + Zoo zoo = new Zoo(); + zoo.animals.add(dog); + zoo.animals.add(cat); + + String result = new ObjectMapper().writeValueAsString(zoo); + + System.out.println(result); + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task33/task3312/Zoo.java b/4.JavaCollections/src/com/javarush/task/task33/task3312/Zoo.java new file mode 100644 index 0000000..40f1159 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task33/task3312/Zoo.java @@ -0,0 +1,47 @@ +package com.javarush.task.task33.task3312; + +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.annotation.JsonTypeName; + +import java.util.ArrayList; +import java.util.List; + +public class Zoo { + public List animals = new ArrayList<>(); + + @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type" ) + @JsonSubTypes({ + @JsonSubTypes.Type(value = Dog.class, name = "dog"), + @JsonSubTypes.Type(value = Cat.class, name = "cat"), + @JsonSubTypes.Type(value = Animal.class, name = "animal") + }) + + public static class Animal { + public Animal(String name) { + this.name = name; + } + + public String name; + } + + @JsonTypeName("dog") + public static class Dog extends Animal { + + public double barkVolume; + + public Dog(String name) { + super(name); + } + } + + @JsonTypeName("cat") + public static class Cat extends Animal { + boolean likesCream; + public int lives; + + public Cat(String name) { + super(name); + } + } +} \ No newline at end of file diff --git "a/4.JavaCollections/src/com/javarush/task/task33/task3312/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task33/task3312/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..f530c94 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task33/task3312/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,22 @@ +taskKey="com.javarush.task.task33.task3312" + +Сериализация зоопарка + +Сделай так, чтобы при сериализации объекта типа Zoo, каждому элементу списка animals был добавлен тип +(dog для класса Dog, cat для класса Cat). +Для проверки можешь использовать метод main класса Solution. + +Было: +{"animals":[{"name":"doggy","barkVolume":0.0},{"name":"catty","lives":0}]} +Должно стать: +{"animals":[{"type":"dog","name":"doggy","barkVolume":0.0},{"type":"cat","name":"catty","lives":0}]} + + +Требования: +1. Класс Zoo.Animal должен быть отмечен аннотацией @JsonTypeInfo. +2. Класс Zoo.Animal должен быть отмечен аннотацией @JsonSubTypes. +3. Класс Zoo.Dog должен быть отмечен аннотацией @JsonTypeName. +4. Класс Zoo.Cat должен быть отмечен аннотацией @JsonTypeName. +5. При сериализации в JSON всем объектам списка animals должен быть добавлен тип и сохранен основной формат (пример в задании). + + diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3401/Solution.java b/4.JavaCollections/src/com/javarush/task/task34/task3401/Solution.java new file mode 100644 index 0000000..4d89a8b --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3401/Solution.java @@ -0,0 +1,21 @@ +package com.javarush.task.task34.task3401; + +/* +Числа Фибоначчи с помощью рекурсии +*/ +public class Solution { + public static void main(String[] args) { + Solution solution = new Solution(); + + System.out.println(solution.fibonacci(9)); //34 + System.out.println(solution.fibonacci(5)); //5 + System.out.println(solution.fibonacci(2)); //1 + System.out.println(solution.fibonacci(1)); //1 + } + + public int fibonacci(int n) { + if (n == 1) { return 1; } + if (n == 0) { return 0; } + return fibonacci(n - 1) + fibonacci(n - 2); + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task34/task3401/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task34/task3401/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..3b55209 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task34/task3401/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,16 @@ +taskKey="com.javarush.task.task34.task3401" + +Числа Фибоначчи с помощью рекурсии + +Почитай про числа Фибоначчи. +Реализуй рекурсивную логику метода fibonacci, где n - это номер элемента в последовательности Фибоначчи. +Не создавай в классе Solution дополнительные поля. + + +Требования: +1. В классе Solution не должны быть созданы дополнительные поля. +2. Метод fibonacci должен принимать порядковый номер искомого числа последовательности Фибоначчи и возвращать его значение. +3. Метод fibonacci не должен быть статическим. +4. Метод fibonacci должен быть рекурсивным. + + diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3402/Solution.java b/4.JavaCollections/src/com/javarush/task/task34/task3402/Solution.java new file mode 100644 index 0000000..c1585d1 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3402/Solution.java @@ -0,0 +1,20 @@ +package com.javarush.task.task34.task3402; + +/* +Факториал с помощью рекурсии +*/ +public class Solution { + public static void main(String[] args) { + Solution solution = new Solution(); + + System.out.println(solution.factorial(9)); //362880 + System.out.println(solution.factorial(0)); //1 + System.out.println(solution.factorial(1)); //1 + } + + public int factorial(int n) { + if (n == 0) return 1; + if (n == 1) return 1; + return n * factorial(n - 1); + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task34/task3402/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task34/task3402/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..45fbc92 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task34/task3402/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,16 @@ +taskKey="com.javarush.task.task34.task3402" + +Факториал с помощью рекурсии + +Почитай про вычисление факториала. +Реализуй рекурсивную логику метода factorial, где n - это число, факториал которого нужно вычислить. +Не создавай в классе Solution дополнительные поля. + + +Требования: +1. В классе Solution не должны быть созданы дополнительные поля. +2. Метод factorial должен возвращать факториал числа принятого в качестве параметра. +3. Метод factorial не должен быть статическим. +4. Метод factorial должен быть рекурсивным. + + diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3403/Solution.java b/4.JavaCollections/src/com/javarush/task/task34/task3403/Solution.java new file mode 100644 index 0000000..646dba7 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3403/Solution.java @@ -0,0 +1,22 @@ +package com.javarush.task.task34.task3403; + +/* +Разложение на множители с помощью рекурсии +*/ +public class Solution { + public void recursion(int n) { + for (int i = 2; i <= n; i++){ + if (n % i == 0){ + System.out.println(i); + recursion(n / i); + break; + } + } + + } + + public static void main(String[] args){ + Solution sol = new Solution(); + sol.recursion(7635); + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task34/task3403/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task34/task3403/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..967aa24 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task34/task3403/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,22 @@ +taskKey="com.javarush.task.task34.task3403" + +Разложение на множители с помощью рекурсии + +Разложить целое число n > 1 на простые множители. +Вывести в консоль через пробел все множители в порядке возрастания. +Написать рекурсивный метод для вычисления простых множителей. +Не создавай в классе Solution дополнительные поля. + +Пример: +132 +Вывод на консоль: +2 2 3 11 + + +Требования: +1. В классе Solution не должны быть созданы дополнительные поля. +2. Метод recursion должен выводить на экран все простые множители числа полученного в качестве параметра (пример в условии). +3. Метод recursion не должен быть статическим. +4. Метод recursion должен быть рекурсивным. + + diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3404/Solution.java b/4.JavaCollections/src/com/javarush/task/task34/task3404/Solution.java new file mode 100644 index 0000000..fe6e8e4 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3404/Solution.java @@ -0,0 +1,422 @@ +package com.javarush.task.task34.task3404; + +import java.io.*; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/* +Рекурсия для мат. выражения +*/ +public class Solution { + public static void main(String[] args) { + Solution solution = new Solution(); + //solution.recursion("sin(2*(-5+1.5*4)+28)", 0); + //solution.recursion("sin(2*(-5+1.5*4 + 3^3)+28)+cos(4) ", 0); //expected output 0.5 6 + //solution.recursion("2*(-5+1.5*4 + 3^3)+(28 +5)*2 ", 0); //expected output 0.5 6 + //Double x = 2*(-5+1.5*4 + 27)+(28 +5)*2; + //System.out.println(); + //System.out.println(x); + String s = "28^sin(1-98098^0)"; + /*System.out.print(s + " expected output 1 4 actually "); + solution.recursion(s, 0); + System.out.println();*/ + + /*s="(-2)^(-2)"; + System.out.print(s + " expected output 0.25 3 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "tan(44+sin(89-cos(180)^2))"; + System.out.print(s + " expected output 1 6 actually "); + solution.recursion(s, 0); + System.out.println(); + + s="89-cos(180)^2"; + System.out.print(s + " expected output 88 3 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "sin(2*(-5+1.5*4)+28)"; + System.out.print(s + " expected output 0.5 6 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "tan(45)"; + System.out.print(s + " expected output 1 1 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "tan(-45)"; + System.out.print(s + " expected output -1 2 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "0.305"; + System.out.print(s + " expected output 0.3 0 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "0.3051"; + System.out.print(s + " expected output 0.31 0 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "(0.3051)"; + System.out.print(s + " expected output 0.31 0 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "1+(1+(1+1)*(1+1))*(1+1)+1"; + System.out.print(s + " expected output 12 8 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "tan(44+sin(89-cos(180)^2))"; + System.out.print(s + " expected output 1 6 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "-2+(-2+(-2)-2*(2+2))"; + System.out.print(s + " expected output -14 8 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "sin(80+(2+(1+1))*(1+1)+2)"; + System.out.print(s + " expected output 1 7 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "1+4/2/2+2^2+2*2-2^(2-1+1)"; + System.out.print(s + " expected output 6 11 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "2^10+2^(5+5)"; + System.out.print(s + " expected output 2048 4 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "1.01+(2.02-1+1/0.5*1.02)/0.1+0.25+41.1"; + System.out.print(s + " expected output 72.96 8 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "0.000025+0.000012"; + System.out.print(s + " expected output 0 1 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "-2-(-2-1-(-2)-(-2)-(-2-2-(-2)-2)-2-2)"; + System.out.print(s + " expected output -3 16 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "cos(3 + 19*3)"; + System.out.print(s + " expected output 0.5 3 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "2*(589+((2454*0.1548/0.01*(-2+9^2))+((25*123.12+45877*25)+25))-547)"; + System.out.print(s + " expected output 8302231.36 14 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "(-1 + (-2))"; + System.out.print(s + " expected output -3 3 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "-sin(2*(-5+1.5*4)+28)"; + System.out.print(s + " expected output -0.5 7 actually "); + solution.recursion(s, 0); + System.out.println(); + + + s = "sin(100)-sin(100)"; + System.out.print(s + " expected output 0 3 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "-(-22+22*2)"; + System.out.print(s + " expected output -22 4 actually "); + solution.recursion(s, 0); + System.out.println();*/ + + s = "-2^(-2)"; + System.out.print(s + " expected output -0.25 3 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "-(-2^(-2))+2+(-(-2^(-2)))"; + System.out.print(s + " expected output 2.5 10 actually "); + solution.recursion(s, 0); + System.out.println(); + + /*s = "(-2)*(-2)"; + System.out.print(s + " expected output 4 3 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "(-2)/(-2)"; + System.out.print(s + " expected output 1 3 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "sin(-30)"; + System.out.print(s + " expected output -0.5 2 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "cos(-30)"; + System.out.print(s + " expected output 0.87 2 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "tan(-30)"; + System.out.print(s + " expected output -0.58 2 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "2+8*(9/4-1.5)^(1+1)"; + System.out.print(s + " expected output 6.5 6 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "0.005 "; + System.out.print(s + " expected output 0.01 0 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "0.0049 "; + System.out.print(s + " expected output 0 0 actually "); + solution.recursion(s, 0); + System.out.println(); + + s = "0+0.304"; + System.out.print(s + " expected output 0.3 1 actually "); + solution.recursion(s, 0);*/ + } + + public void recursion(final String expression, int countOperation) { + //System.out.println(expression); + Locale.setDefault(Locale.ENGLISH); + + String handledExpression = ""; + /*if (!expression.contains("(")) { + handledExpression = new String(expression); + }*/ + boolean isFirstEntry = countOperation == 0; + int countOperForOutput = 0; + + // Считаем операции сразу же, при первом входе в рекурсию. + // Все остальные обращения к countOperation - старая реализация + + if (isFirstEntry) { + Pattern pattern = Pattern.compile("[\\+\\-\\*\\^\\/]"); + Pattern patternSin = Pattern.compile("sin"); + Pattern patternCos = Pattern.compile("cos"); + Pattern patternTan = Pattern.compile("tan"); + Matcher match = pattern.matcher(expression); + while (match.find()) { + countOperation +=1; + } + + Matcher matchSin = patternSin.matcher(expression); + while (matchSin.find()){ + countOperation +=1; + } + + Matcher matchCos = patternCos.matcher(expression); + while (matchCos.find()){ + countOperation +=1; + } + + Matcher matchTan = patternTan.matcher(expression); + while (matchTan.find()){ + countOperation +=1; + } + + countOperForOutput = countOperation; + } + + int handledExpressionStartIndex = 0; + for (int i = 0; i < expression.length(); i ++){ + if (String.valueOf(expression.charAt(i)).equals("(")) { + /*handledExpression = "";*/ + int newExpressionStartIndex = i + 1; + int parenthesisCounter = 1; + //int lengthCounter = i; + i++; + while ( (parenthesisCounter != 0) && (i < expression.length() )) { + if (String.valueOf(expression.charAt(i)).equals("(")) { + parenthesisCounter += 1; + }else if (String.valueOf(expression.charAt(i)).equals(")")) { + parenthesisCounter -= 1; + } + i++; + } + + Double result = 0.0; + /*try ( + BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + ) { + result = Double.valueOf(reader.readLine()); + } catch (IOException e) { + }*/ + PrintStream oldOut = System.out; + ByteArrayOutputStream outArray = new ByteArrayOutputStream(); + PrintStream out = new PrintStream(outArray); + System.setOut(out); + + recursion(expression.substring(newExpressionStartIndex, i - 1), countOperation); + System.setOut(oldOut); + result = Double.valueOf(outArray.toString().substring(0, outArray.toString().indexOf(" "))); + countOperation = Integer.valueOf(outArray.toString().substring(outArray.toString().indexOf(" ") + 1)); + + handledExpression = handledExpression + expression.substring(handledExpressionStartIndex, newExpressionStartIndex - 1) + + new BigDecimal(result).setScale(4, RoundingMode.HALF_UP).toString(); + /*expression.substring(i);*/ + handledExpressionStartIndex = i; + int j = 0; + } + } + handledExpression = handledExpression + expression.substring(handledExpressionStartIndex); + if (!handledExpression.contains("(") && !handledExpression.contains(")")) { + int[] forCountOperRet = new int[1]; + forCountOperRet[0] = countOperation; + Double result = letsCountExpression(handledExpression, forCountOperRet); + /*byte[] byteArray = new byte[1]; + byteArray[0] = result.byteValue(); + ByteArrayInputStream newIn = new ByteArrayInputStream(byteArray); + System.setIn(newIn);*/ + countOperation = forCountOperRet[0]; + + DecimalFormat df = isFirstEntry ? new DecimalFormat("#.##") : new DecimalFormat("#.######"); + + System.out.format("%s %d", df.format(result), countOperForOutput); + + /*ByteArrayOutputStream outArray = new ByteArrayOutputStream(); + outArray.write(result.byteValue()); + PrintStream out = new PrintStream(outArray); + System.setOut(out);*/ + + } + //implement + } + + public double letsCountExpression(String expression, int[] countOperations){ + ArrayList numbers = new ArrayList(); + ArrayList almostNumbers = new ArrayList(); + ArrayList operations = new ArrayList<>(); + expression = expression.replaceAll(" ", ""); + int startIndex = 0; + /*if (expression.charAt(0) == '-') { + expression = "0" + expression; + }*/ + + for (int i = 1; i < expression.length(); i++) { + if (expression.charAt(i) == '+' + || expression.charAt(i) == '/' + || expression.charAt(i) == '-' + || expression.charAt(i) == '*' + || expression.charAt(i) == '^') { + if (expression.charAt(i+1) == '-' ) { + almostNumbers.add(expression.substring(startIndex, i)); + operations.add(String.valueOf(expression.charAt(i))); + startIndex = i + 1; + i++; + } else if (expression.charAt(i-1) == 's' || expression.charAt(i-1) == 'n' ){ + + } else { + almostNumbers.add(expression.substring(startIndex, i)); + operations.add(String.valueOf(expression.charAt(i))); + startIndex = i + 1; + } + } + } + /*for (int i = 0; i < expression.length(); i++){ + if (expression.charAt(i) == '+' + || expression.charAt(i) == '-' + || expression.charAt(i) == '*' + || expression.charAt(i) == '^' ) { + + + almostNumbers.add(expression.substring(startIndex, i)); + //numbers.add(Double.valueOf(expression.substring(startIndex, i))); + operations.add(String.valueOf(expression.charAt(i))); + startIndex = i + 1; + } + }*/ + almostNumbers.add(expression.substring(startIndex, expression.length())); + //numbers.add(Double.valueOf(expression.substring(startIndex, expression.length()))); + + for (int i = 0; i < almostNumbers.size(); i++){ + if (almostNumbers.get(i).contains("sin")) { + numbers.add(Math.sin(Math.toRadians(Double.valueOf(almostNumbers.get(i).replace("sin", ""))))); + countOperations[0] += 1; + }else if (almostNumbers.get(i).contains("cos")){ + numbers.add(Math.cos(Math.toRadians(Double.valueOf(almostNumbers.get(i).replace("cos", ""))))); + countOperations[0] += 1; + }else if (almostNumbers.get(i).contains("tan")){ + numbers.add(Math.tan(Math.toRadians(Double.valueOf(almostNumbers.get(i).replace("tan", ""))))); + countOperations[0] += 1; + }else { + numbers.add(Double.valueOf(almostNumbers.get(i))); + } + } + + countOperations[0] += operations.size(); + if (operations.size() == 0){ + return numbers.get(0); + } else { + for (int i = 0; i < operations.size(); i++){ + if (operations.get(i).equals("^")){ + numbers.add(i, Math.pow(numbers.get(i), numbers.get(i+1))); + numbers.remove(i + 1); + numbers.remove(i + 1); + operations.remove(i); + i--; + } + } + + for (int i = 0; i < operations.size(); i++){ + if (operations.get(i).equals("/")){ + numbers.add(i, numbers.get(i) / numbers.get(i+1)); + numbers.remove(i + 1); + numbers.remove(i + 1); + operations.remove(i); + i--; + } + } + + for (int i = 0; i < operations.size(); i++){ + if (operations.get(i).equals("*")){ + numbers.add(i, numbers.get(i) * numbers.get(i+1)); + numbers.remove(i + 1); + numbers.remove(i + 1); + operations.remove(i); + i--; + } + } + + double result = numbers.get(0); + for (int i = 0; i < operations.size(); i++){ + if (operations.get(i).equals("+")){ + result = result + numbers.get(i+1); + }else { + result = result - numbers.get(i+1); + } + } + return result; + } + } + + public Solution() { + //don't delete + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task34/task3404/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task34/task3404/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..6850424 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task34/task3404/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,25 @@ +taskKey="com.javarush.task.task34.task3404" + +Рекурсия для мат. выражения + +На вход подается строка - математическое выражение. +Выражение включает целые и дробные числа, скобки (), пробелы, знак отрицания -, возведение в степень ^, sin(x), cos(x), tan(x) +Для sin(x), cos(x), tan(x) выражение внутри скобок считать градусами, например, cos(3 + 19*3)=0.5 +Степень задается так: a^(1+3) и так a^4, что эквивалентно a*a*a*a. +С помощью рекурсии вычислить выражение и количество математических операций. Вывести через пробел результат в консоль. +Результат выводить с точностью до двух знаков, для 0.33333 вывести 0.33, использовать стандартный принцип округления. +Не создавай в классе Solution дополнительные поля. +Не пиши косвенную рекурсию. +Пример, состоящий из операций sin * - + * +: +sin(2*(-5+1.5*4)+28) +Результат: +0.5 6 + + +Требования: +1. В классе Solution не должны быть созданы дополнительные поля. +2. Метод recursion должен выводить на экран результат вычисления заданного выражения (пример в условии). +3. Метод recursion не должен быть статическим. +4. Метод recursion должен быть рекурсивным. + + diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3405/Solution.java b/4.JavaCollections/src/com/javarush/task/task34/task3405/Solution.java new file mode 100644 index 0000000..5f63b3a --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3405/Solution.java @@ -0,0 +1,82 @@ +package com.javarush.task.task34.task3405; + +import java.lang.ref.SoftReference; +import java.util.ArrayList; +import java.util.List; + +/* +Мягкие ссылки +*/ +public class Solution { + public static Helper helper = new Helper(); + + public static class Monkey { + private String name; + + public Monkey(String name) { + this.name = name; + } + + protected void finalize() { + Helper.isFinalized = true; + System.out.format("Bye-Bye, %s!\n", name); + } + } + + public static void main(String args[]) throws InterruptedException { + helper.startTime(); + + Monkey monkey = new Monkey("Simka"); + + SoftReference reference = new SoftReference(monkey); + //Add reference here + + helper.callGC(); + + monkey = null; + + helper.callGC(); + helper.heapConsuming(); + + if (reference.get() == null) + System.out.println("Finalized"); + + helper.finish(); + } + + public static class Helper { + public static boolean isFinalized; + + private long startTime; + + void startTime() { + this.startTime = System.currentTimeMillis(); + } + + int getTime() { + return (int) (System.currentTimeMillis() - startTime) / 1000; + } + + void callGC() throws InterruptedException { + System.gc(); + Thread.sleep(1000); + } + + void heapConsuming() { + try { + List heap = new ArrayList(10000000); + while (!isFinalized) { + heap.add(new Solution()); + } + } catch (OutOfMemoryError e) { + System.out.println("Out of memory error raised"); + } + } + + public void finish() { + System.out.println("Done"); + System.out.println("It took " + getTime() + " sec"); + + } + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task34/task3405/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task34/task3405/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..e433a41 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task34/task3405/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,15 @@ +taskKey="com.javarush.task.task34.task3405" + +Мягкие ссылки + +Разберись в примере. +Внутри метода main после создания объекта типа Monkey создай мягкую ссылку (SoftReference) на него. + + +Требования: +1. В методе main должен быть создан объект типа Monkey с именем "Simka". +2. В методе main должен быть создан SoftReference на объект monkey. +3. Класс Monkey должен быть публичным. +4. Класс Monkey должен быть статическим. + + diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3406/Solution.java b/4.JavaCollections/src/com/javarush/task/task34/task3406/Solution.java new file mode 100644 index 0000000..487e123 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3406/Solution.java @@ -0,0 +1,81 @@ +package com.javarush.task.task34.task3406; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; + +/* +Слабые ссылки +*/ +public class Solution { + public static Helper helper = new Helper(); + + public static class Monkey { + private String name; + + public Monkey(String name) { + this.name = name; + } + + protected void finalize() { + Helper.isFinalized = true; + System.out.format("Bye-Bye, %s!\n", name); + } + } + + public static void main(String args[]) throws InterruptedException { + helper.startTime(); + + Monkey monkey = new Monkey("Simka"); + + WeakReference reference = new WeakReference(monkey); + //Add reference here + + helper.callGC(); + + monkey = null; + + helper.callGC(); + helper.heapConsuming(); + + if (reference.get() == null) + System.out.println("Finalized"); + + helper.finish(); + } + + public static class Helper { + public static boolean isFinalized; + + private long startTime; + + void startTime() { + this.startTime = System.currentTimeMillis(); + } + + int getTime() { + return (int) (System.currentTimeMillis() - startTime) / 1000; + } + + void callGC() throws InterruptedException { + System.gc(); + Thread.sleep(1000); + } + + void heapConsuming() { + try { + List heap = new ArrayList(100000); + while (!isFinalized) { + heap.add(new Solution()); + } + } catch (OutOfMemoryError e) { + System.out.println("Out of memory error raised"); + } + } + + public void finish() { + System.out.println("Done"); + System.out.println("It took " + getTime() + " sec"); + } + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task34/task3406/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task34/task3406/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..3a81f61 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task34/task3406/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,15 @@ +taskKey="com.javarush.task.task34.task3406" + +Слабые ссылки + +Разберись в примере. +Внутри метода main после создания объекта типа Monkey создай слабую ссылку (WeakReference) на него. + + +Требования: +1. В методе main должен быть создан объект типа Monkey с именем "Simka". +2. В методе main должен быть создан WeakReference на объект monkey. +3. Класс Monkey должен быть публичным. +4. Класс Monkey должен быть статическим. + + diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3407/Solution.java b/4.JavaCollections/src/com/javarush/task/task34/task3407/Solution.java new file mode 100644 index 0000000..fff39b5 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3407/Solution.java @@ -0,0 +1,95 @@ +package com.javarush.task.task34.task3407; + +import java.lang.ref.PhantomReference; +import java.lang.ref.ReferenceQueue; +import java.util.ArrayList; +import java.util.List; + +/* +Призрачные ссылки +*/ +public class Solution { + public static Helper helper = new Helper(); + + public static class Monkey { + } + + public static void main(String args[]) throws InterruptedException { + helper.startTime(); + List> list = helper.getFilledList(); + + //before GC + helper.checkListWithReferences(list, "before"); + + helper.callGC(); + helper.heapConsuming(); + + //after GC + helper.checkListWithReferences(list, "after"); + + helper.finish(); + } + + public static class Helper { + private ReferenceQueue queue = new ReferenceQueue<>(); + + private long startTime; + + void startTime() { + this.startTime = System.currentTimeMillis(); + } + + int getTime() { + return (int) (System.currentTimeMillis() - startTime) / 1000; + } + + void callGC() throws InterruptedException { + System.gc(); + Thread.sleep(1000); + } + + public ReferenceQueue getQueue() { + return queue; + } + + void heapConsuming() { + try { + List heap = new ArrayList(100000); + while (true) { + heap.add(new Solution()); + } + } catch (OutOfMemoryError e) { + System.out.println("Out of memory error raised"); + } + } + + public void checkListWithReferences(List> list, String string) { + int count = 0; + for (PhantomReference reference : list) { + if (reference.isEnqueued()) { + count++; + } + } + + System.out.println(String.format("The enqueue reference count is %d (%s GC was called)", count, string)); + } + + public List> getFilledList() { + ReferenceQueue queue = getQueue(); + List> list = new ArrayList<>(); + for (int i = 0; i < 200; i++){ + list.add(new PhantomReference(new Monkey(), queue)); + } + return list; + } + + public void finish() throws InterruptedException { + int count = 0; + while (queue.poll() != null) { + count++; + } + System.out.println(count + " objects are in the queue of phantom reference"); + System.out.println("It took " + getTime() + " sec"); + } + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task34/task3407/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task34/task3407/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..39a9f4a --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task34/task3407/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,18 @@ +taskKey="com.javarush.task.task34.task3407" + +Призрачные ссылки + +Разберись в примере. +Реализуй логику метода getFilledList класса Helper: +1) создай список, который сможет хранить призрачные ссылки на объекты Monkey +2) добавь в список 200 ссылок, используйте очередь helper.getQueue() +3) верни заполненный список + + +Требования: +1. Метод getFilledList должен возвращать список заполненный фантомными ссылками на объекты типа Monkey. +2. Метод getFilledList должен возвращать список из 200 элементов. +3. Класс Helper не должен быть приватным. +4. Метод getFilledList не должен быть приватным. + + diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3408/Cache.java b/4.JavaCollections/src/com/javarush/task/task34/task3408/Cache.java new file mode 100644 index 0000000..3e540db --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3408/Cache.java @@ -0,0 +1,44 @@ +package com.javarush.task.task34.task3408; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Map; +import java.util.WeakHashMap; + +public class Cache { + private Map cache = new WeakHashMap(); //TODO add your code here + + public V getByKey(K key, Class clazz) throws Exception { + V object = cache.get(key); + if (object == null) { + Constructor constr = clazz.getConstructor(key.getClass()); + object = constr.newInstance(key); + cache.put(key, object); + } + //TODO add your code here + return object; + } + + public boolean put(V obj) { + try { + Method meth = obj.getClass().getDeclaredMethod("getKey", null); + meth.setAccessible(true); + K key = (K) meth.invoke(obj,null); + cache.put(key, obj); + return true ; + } catch (NoSuchMethodException e) { + return false; + } catch (InvocationTargetException e) { + return false; + } catch (IllegalAccessException e) { + return false; + } + //TODO add your code here + + } + + public int size() { + return cache.size(); + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3408/Solution.java b/4.JavaCollections/src/com/javarush/task/task34/task3408/Solution.java new file mode 100644 index 0000000..27a540e --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3408/Solution.java @@ -0,0 +1,65 @@ +package com.javarush.task.task34.task3408; + +/* +Кэширование +*/ +public class Solution { + public static void main(String[] args) throws Exception { + SomeKey someKey = new SomeKey(); + someKey.name = "test"; + + SomeKey someKeyNew = new SomeKey(); + someKeyNew.name = "testNew"; + + SomeValue value = new SomeValue(someKey); + + Cache cache = new Cache<>(); + cache.put(value); + + SomeValue valueFromCacheExisted = cache.getByKey(someKey, SomeValue.class); + System.out.println(valueFromCacheExisted); + + SomeValue valueFromCacheNew = cache.getByKey(someKeyNew, SomeValue.class); + System.out.println(valueFromCacheNew); + + System.out.println(cache.size()); + /* expected output: + SomeValue{myKey=SomeKey{name='test'}} + SomeValue{myKey=SomeKey{name='testNew'}} + 2 + */ + } + + public static class SomeKey { + String name; + + @Override + public String toString() { + return "SomeKey{" + + "name='" + name + '\'' + + '}'; + } + } + + public static class SomeValue { + private SomeKey myKey; + + public SomeValue() { + } + + public SomeValue(SomeKey myKey) { //use this constructor + this.myKey = myKey; + } + + private SomeKey getKey() { + return myKey; + } + + @Override + public String toString() { + return "SomeValue{" + + "myKey=" + myKey + + '}'; + } + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task34/task3408/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task34/task3408/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..15ab328 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task34/task3408/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,31 @@ +taskKey="com.javarush.task.task34.task3408" + +Кэширование + +Класс Cache - универсальный параметризированный класс для кеширования объектов. +Он работает с классами(дженерик тип Т), у которых обязан быть: +а) публичный конструктор с одним параметром типа K; +б) метод K getKey() с любым модификатором доступа. + +Задание: +1. Выбери правильный тип для поля cache. Map cache должен хранить ключи, на которые есть активные ссылки. +Если нет активных ссылок на ключи, то они вместе со значениями должны автоматически удаляться из cache. +2. Реализуй логику метода getByKey: +2.1. Верни объект из cache для ключа key. +2.2. Если объекта не существует в кэше, то добавьте в кэш новый экземпляр используя рефлексию, см. пункт а). +3. Реализуй логику метода put: +3.1. Используя рефлексию получи ссылку на метод, описанный в пункте б). +3.2. Используя рефлексию разреши к нему доступ. +3.3. Используя рефлексию вызови метод getKey у объекта obj, таким образом ты получишь ключ key. +3.4. Добавь в кэш пару . +3.5. Верни true, если метод отработал корректно, false в противном случае. Исключения игнорируй. + + +Требования: +1. Поле cache должно быть инициализировано объектом типа WeakHashMap. +2. Метод getByKey должен возвращать объект из кеша. +3. Метод getByKey должен добавлять объект в кеш если его там нет. +4. Метод put должен извлекать из переданного объекта ключ и добавлять в кеш пару . +5. Метод put должен возвращать true, если он отработал корректно, иначе false. + + diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3409/Solution.java b/4.JavaCollections/src/com/javarush/task/task34/task3409/Solution.java new file mode 100644 index 0000000..61bf5ff --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3409/Solution.java @@ -0,0 +1,22 @@ +package com.javarush.task.task34.task3409; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Properties; + +/* +Настраиваем логгер +*/ +public class Solution { + public static void main(String args[]) throws IOException { + String logProperties = "src/" + Solution.class.getPackage().getName().replaceAll("[.]", "/") + "/log4j.properties"; + Path path = Paths.get(logProperties).toAbsolutePath(); + try (InputStream is = new FileInputStream(path.toFile())) { + Properties properties = new Properties(); + properties.load(is); + } + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3409/log4j.properties b/4.JavaCollections/src/com/javarush/task/task34/task3409/log4j.properties new file mode 100644 index 0000000..ef04276 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3409/log4j.properties @@ -0,0 +1,21 @@ +log4j.rootLogger=WARN, file, stdout + +# Direct log messages to a log file +log4j.appender.file=org.apache.log4j.RollingFileAppender +log4j.appender.file.threshold=WARN +log4j.appender.file.File=D:\\log\\runApp.log +log4j.appender.file.MaxFileSize=5MB +log4j.appender.file.MaxBackupIndex=6 +log4j.appender.file.layout=org.apache.log4j.PatternLayout +log4j.appender.file.layout.ConversionPattern= %-5p %c{1}:%L - %m%n + +# Direct log messages to stdout +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.threshold=ERROR +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} + +log4j.logger.org.springframework=ERROR +log4j.logger.org.hibernate=ERROR +log4j.logger.org.apache.cxf=ERROR diff --git "a/4.JavaCollections/src/com/javarush/task/task34/task3409/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task34/task3409/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..d797af1 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task34/task3409/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,26 @@ +taskKey="com.javarush.task.task34.task3409" + +Настраиваем логгер + +Дан файл log4j.properties, который содержит настройки логгера для разработчиков. +Изменились требования к логированию для продакшена. + +Список изменений, которые нужно сделать: +1) Размер файла для логирования не должен превышать 5 мегабайт. +2) Файлы лога должны храниться на диске D в директории log, называться должны runApp.log. +3) Файлы лога должны содержать 6 последних файлов. Если шестой файл уже заполнен(имеет размер 5Мб), +то нужно удалить самый первый и создать новый. +4) Уровень вывода сообщений в консоль нужно установить на уровне ERROR. +5) Минимальный уровень логирования выставить в WARN. + +Отредактируй файл log4j.properties в соответствии с предоставленными требованиями. + + +Требования: +1. Размер файла для логирования не должен превышать 5 мегабайт. +2. Файлы лога должны храниться на диске D в директории log, называться должны runApp.log. +3. Файлы лога должны содержать 6 последних файлов. Если шестой файл уже заполнен(имеет размер 5Мб), то нужно удалить самый первый и создать новый. +4. Уровень вывода сообщений в консоль нужно установить на уровне ERROR. +5. Минимальный уровень логирования выставить в WARN. + + diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3411/Solution.java b/4.JavaCollections/src/com/javarush/task/task34/task3411/Solution.java new file mode 100644 index 0000000..140f328 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3411/Solution.java @@ -0,0 +1,18 @@ +package com.javarush.task.task34.task3411; + +/* +Ханойские башни +*/ + +import java.util.HashSet; + +public class Solution { + public static void main(String[] args) { + int count = 3; + moveRing('A', 'B', 'C', count); + } + + public static void moveRing(char a, char b, char c, int count) { + //напишите тут ваш код + } +} \ No newline at end of file diff --git "a/4.JavaCollections/src/com/javarush/task/task34/task3411/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task34/task3411/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..9b93a5a --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task34/task3411/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,42 @@ +taskKey="com.javarush.task.task34.task3411" + +Ханойские башни + +Имеется три стержня. На стержень A нанизаны count колец, причем кольца отличаются размером и лежат меньшее +на большем. Требуется перенести пирамиду из count колец с стержня A на стержень B за наименьшее число ходов. +За один раз разрешается переносить только одно кольцо, причем нельзя класть большее кольцо на меньшее. +Нужно реализовать публичный статический метод void moveRing(char a, char b, char c, int count), который +выведет последовательность действий, необходимых для перемещения колец со стержня A на стержень B. +Параметры метода: +char a - имя стержня, на котором в начале находятся все кольца; +char b - имя стержня, на который нужно перенести все кольца; +char c - имя вспомогательного стержня; +int count - общее количество колец, которые необходимо перенести. +Задачу нужно решать используя рекурсивный вызов метода moveRing. + +Пример1: +Метод moveRing вызывается с параметрами: 'A', 'B', 'C', 1 +Ожидаемый вывод: +from A to B + +Пример2: +Метод moveRing вызывается с параметрами: 'A', 'B', 'C', 3 +Ожидаемый вывод: +from A to B +from A to C +from B to C +from A to B +from C to A +from C to B +from A to B + +Подсказка: общее количество действий равно 2 в степени count минус 1. + + +Требования: +1. В классе Solution должен существовать публичный статический метод void moveRing(char, char, char, int). +2. Методе moveRing должен быть рекурсивным. +3. Количество действий по перемещению колец должно быть равно 2 в степени count минус 1. +4. Вывод метода moveRing должен соответствовать условию. + + diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3412/Solution.java b/4.JavaCollections/src/com/javarush/task/task34/task3412/Solution.java new file mode 100644 index 0000000..df0f29d --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3412/Solution.java @@ -0,0 +1,80 @@ +package com.javarush.task.task34.task3412; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Date; + +/* +Добавление логирования в класс +*/ + +public class Solution { + private static final Logger logger = LoggerFactory.getLogger(Solution.class); + + private int value1; + private String value2; + private Date value3; + + public Solution(int value1, String value2, Date value3) { + logger.debug("constructor"); + this.value1 = value1; + this.value2 = value2; + this.value3 = value3; + } + + public static void main(String[] args) { + + } + + public void calculateAndSetValue3(long value) { + logger.trace("calculateAndSetValue3" + value); + value -= 133; + + if (value > Integer.MAX_VALUE) { + value1 = (int) (value / Integer.MAX_VALUE); + logger.debug("value1 if true"); + } else { + value1 = (int) value; + logger.debug("value1 if false"); + } + } + + public void printString() { + logger.trace("printString"); + if (value2 != null) { + System.out.println(value2.length()); + } + } + + public void printDateAsLong() { + logger.trace("printDateAsLong"); + if (value3 != null) { + System.out.println(value3.getTime()); + } + } + + public void divide(int number1, int number2) { + logger.trace("divide" + "number1=" + number1 + " number2=" + number2); + try { + System.out.println(number1 / number2); + } catch (ArithmeticException e) { + logger.error("ArichmeticExceprion", e); + } + } + + public void setValue1(int value1) { + logger.debug("setValue1"); + this.value1 = value1; + } + + public void setValue2(String value2) { + logger.debug("setValue2"); + this.value2 = value2; + } + + public void setValue3(Date value3) { + logger.debug("setValue3"); + this.value3 = value3; + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task34/task3412/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task34/task3412/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..d0f9aca --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task34/task3412/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,26 @@ +taskKey="com.javarush.task.task34.task3412" + +Добавление логирования в класс + +В Intellij IDEA Alt+Ctrl+Shift+S -> Global Libraries -> New Global Library -> From Maven... +В строке поиска в открывшемся окне укажи: org.slf4j:slf4j-api:1.7.23 -> Поиск (Shift+Enter) +Укажи куда скачать библиотеку логирования. +Выбрери к какому модулю проекта подключить библиотеку slf4j-api: нужно выбрать 4.JavaCollections -> OK +Apply -> OK. + +Посмотри где бы ты в классе Solution применил какой уровень логирования? + +В класс Solution нужно добавить вызовы методов уровня: +error - 1 раз; +debug - 6 раз - используй при изменениях значений полей класса; +trace - 4 раза - используй для отслеживания пути выполнения програмы; +Сообщения в логах старайся писать информативные. +Остальной код не изменяй. + +Требования: +1. В классе Solution должно существовать приватное статическое финальное поле logger. +2. Добавь логирование уровня error один раз. +3. Добавь логирование уровня debug шесть раз. +4. Добавь логирование уровня trace четыре раза. + + diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3413/AnyObject.java b/4.JavaCollections/src/com/javarush/task/task34/task3413/AnyObject.java new file mode 100644 index 0000000..b4a3109 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3413/AnyObject.java @@ -0,0 +1,57 @@ +package com.javarush.task.task34.task3413; + +import java.util.Calendar; +import java.util.GregorianCalendar; + +public class AnyObject { + + private Long id; + private String name; + private Calendar creationTime = new GregorianCalendar(); + private String additionalDescription; + + public AnyObject(Long id, String name, String additionalDescription) { + this.id = id; + if (name != null) { + this.name = name; + } else { + this.name = "AnyObject#" + id; + } + if (additionalDescription != null) { + this.additionalDescription = additionalDescription; + } else { + this.additionalDescription = "This is object #" + id; + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + AnyObject that = (AnyObject) o; + + if (!id.equals(that.id)) return false; + if (!name.equals(that.name)) return false; + return creationTime.equals(that.creationTime); + + } + + @Override + public int hashCode() { + int result = id.hashCode(); + result = 31 * result + name.hashCode(); + result = 31 * result + creationTime.hashCode(); + return result; + } + + @Override + public String toString() { + return "AnyObject{" + + "id = " + id + + ", name = '" + name + '\'' + + ", creationTime = " + creationTime.getTime() + + ", additionalDescription = '" + additionalDescription + '\'' + + '}'; + } +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3413/SoftCache.java b/4.JavaCollections/src/com/javarush/task/task34/task3413/SoftCache.java new file mode 100644 index 0000000..81211b3 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3413/SoftCache.java @@ -0,0 +1,51 @@ +package com.javarush.task.task34.task3413; + +import java.lang.ref.SoftReference; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class SoftCache { + private Map> cacheMap = new ConcurrentHashMap<>(); + + public AnyObject get(Long key) { + SoftReference softReference = cacheMap.get(key); + AnyObject obj = null; + if (softReference == null) { + return null; + }else { + obj = softReference.get(); + softReference.clear(); + return obj; + } + + //напишите тут ваш код + } + + public AnyObject put(Long key, AnyObject value) { + + SoftReference softReference = cacheMap.put(key, new SoftReference<>(value)); + value = null; + AnyObject obj = null; + if (softReference == null) { + return null; + }else { + obj = softReference.get(); + softReference.clear(); + return obj; + } + //напишите тут ваш код + } + + public AnyObject remove(Long key) { + SoftReference softReference = cacheMap.remove(key); + AnyObject obj = null; + if (softReference == null) { + return null; + }else { + obj = softReference.get(); + softReference.clear(); + return obj; + } + //напишите тут ваш код + } +} \ No newline at end of file diff --git a/4.JavaCollections/src/com/javarush/task/task34/task3413/Solution.java b/4.JavaCollections/src/com/javarush/task/task34/task3413/Solution.java new file mode 100644 index 0000000..b37d74e --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task34/task3413/Solution.java @@ -0,0 +1,15 @@ +package com.javarush.task.task34.task3413; + +/* +Кеш на основании SoftReference +*/ + +public class Solution { + public static void main(String[] args) { + SoftCache cache = new SoftCache(); + + for (long i = 0; i < 2_500_000; i++) { + cache.put(i, new AnyObject(i, null, null)); + } + } +} \ No newline at end of file diff --git "a/4.JavaCollections/src/com/javarush/task/task34/task3413/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task34/task3413/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..68d93d4 --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task34/task3413/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,29 @@ +taskKey="com.javarush.task.task34.task3413" + +Кеш на основании SoftReference + +Реализуй логику методов get, put, remove класса SoftCache: + +Метод AnyObject get(Long key) должен возвращать объект типа AnyObject из мапы cacheMap по ключу key. Если +такого ключа в cacheMap нет - верни null. + +Метод AnyObject put(Long key, AnyObject value) должен добавлять в мапу пару key : value. Метод должен +вернуть null, если в cacheMap по такому ключу ранее не было значения. Иначе - верни предыдущее значение +value по этому ключу. Не забудь вызвать метод clear() у объекта типа SoftReference. + +Метод AnyObject remove(Long key) должен удалить из мапы cacheMap пару key : value по ключу key. Метод должен +вернуть null, если в cacheMap по такому ключу ранее не было значения. Иначе - верни предыдущее значение +value по этому ключу. Не забудь вызвать метод clear() у объекта типа SoftReference. + +Не изменяй класс AnyObject. +Метод main не принимает участия в тестировании. + + +Требования: +1. Класс AnyObject не должен быть изменен. +2. В классе SoftCache должно существовать приватное поле Map> cacheMap. +3. Реализуй метод get согласно условию. +4. Реализуй метод put согласно условию. +5. Реализуй метод remove согласно условию. + + diff --git a/4.JavaCollections/src/com/javarush/task/task37/task3702/AbstractFactory.java b/4.JavaCollections/src/com/javarush/task/task37/task3702/AbstractFactory.java new file mode 100644 index 0000000..e14082c --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task37/task3702/AbstractFactory.java @@ -0,0 +1,8 @@ +package com.javarush.task.task37.task3702; + +/** + * Created by Archmage on 28.07.2017. + */ +public interface AbstractFactory { + Human getPerson(int age); +} diff --git a/4.JavaCollections/src/com/javarush/task/task37/task3702/FactoryProducer.java b/4.JavaCollections/src/com/javarush/task/task37/task3702/FactoryProducer.java new file mode 100644 index 0000000..e987b43 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task37/task3702/FactoryProducer.java @@ -0,0 +1,26 @@ +package com.javarush.task.task37.task3702; + +import com.javarush.task.task37.task3702.female.FemaleFactory; +import com.javarush.task.task37.task3702.male.MaleFactory; + +/** + * Created by Archmage on 28.07.2017. + */ +public class FactoryProducer { + public enum HumanFactoryType{ + MALE, + FEMALE + } + + public static AbstractFactory getFactory(HumanFactoryType type){ + switch (type){ + case MALE: + return new MaleFactory(); + + case FEMALE: + return new FemaleFactory(); + + } + return null; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task37/task3702/Human.java b/4.JavaCollections/src/com/javarush/task/task37/task3702/Human.java new file mode 100644 index 0000000..7a71a45 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task37/task3702/Human.java @@ -0,0 +1,7 @@ +package com.javarush.task.task37.task3702; + +/** + * Created by Archmage on 28.07.2017. + */ +public interface Human { +} diff --git a/4.JavaCollections/src/com/javarush/task/task37/task3702/Solution.java b/4.JavaCollections/src/com/javarush/task/task37/task3702/Solution.java new file mode 100644 index 0000000..f33bf8f --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task37/task3702/Solution.java @@ -0,0 +1,18 @@ +package com.javarush.task.task37.task3702; + +public class Solution { + public static void main(String[] args) { + AbstractFactory factory = FactoryProducer.getFactory(FactoryProducer.HumanFactoryType.FEMALE); + useFactory(factory); + + factory = FactoryProducer.getFactory(FactoryProducer.HumanFactoryType.MALE); + useFactory(factory); + } + + public static void useFactory(AbstractFactory factory) { + System.out.println(factory.getPerson(99)); + System.out.println(factory.getPerson(4)); + System.out.println(factory.getPerson(15)); + } + +} diff --git a/4.JavaCollections/src/com/javarush/task/task37/task3702/female/FemaleFactory.java b/4.JavaCollections/src/com/javarush/task/task37/task3702/female/FemaleFactory.java new file mode 100644 index 0000000..c309e38 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task37/task3702/female/FemaleFactory.java @@ -0,0 +1,19 @@ +package com.javarush.task.task37.task3702.female; + +import com.javarush.task.task37.task3702.AbstractFactory; +import com.javarush.task.task37.task3702.Human; + +/** + * Created by Archmage on 28.07.2017. + */ +public class FemaleFactory implements AbstractFactory { + public Human getPerson(int age){ + if (age <= KidGirl.MAX_AGE){ + return new KidGirl(); + }else if (age <= TeenGirl.MAX_AGE){ + return new TeenGirl(); + }else { + return new Woman(); + } + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task37/task3702/female/KidGirl.java b/4.JavaCollections/src/com/javarush/task/task37/task3702/female/KidGirl.java new file mode 100644 index 0000000..effea4b --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task37/task3702/female/KidGirl.java @@ -0,0 +1,15 @@ +package com.javarush.task.task37.task3702.female; + +import com.javarush.task.task37.task3702.Human; + +/** + * Created by Archmage on 28.07.2017. + */ +public class KidGirl implements Human { + public static final int MAX_AGE = 12; + + @Override + public String toString() { + return "KidGirl{}"; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task37/task3702/female/TeenGirl.java b/4.JavaCollections/src/com/javarush/task/task37/task3702/female/TeenGirl.java new file mode 100644 index 0000000..b241727 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task37/task3702/female/TeenGirl.java @@ -0,0 +1,15 @@ +package com.javarush.task.task37.task3702.female; + +import com.javarush.task.task37.task3702.Human; + +/** + * Created by Archmage on 28.07.2017. + */ +public class TeenGirl implements Human { + public static final int MAX_AGE = 19; + + @Override + public String toString() { + return "TeenGirl{}"; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task37/task3702/female/Woman.java b/4.JavaCollections/src/com/javarush/task/task37/task3702/female/Woman.java new file mode 100644 index 0000000..6e09793 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task37/task3702/female/Woman.java @@ -0,0 +1,13 @@ +package com.javarush.task.task37.task3702.female; + +import com.javarush.task.task37.task3702.Human; + +/** + * Created by Archmage on 28.07.2017. + */ +public class Woman implements Human { + @Override + public String toString() { + return "Woman{}"; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task37/task3702/male/KidBoy.java b/4.JavaCollections/src/com/javarush/task/task37/task3702/male/KidBoy.java new file mode 100644 index 0000000..d6d33a6 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task37/task3702/male/KidBoy.java @@ -0,0 +1,15 @@ +package com.javarush.task.task37.task3702.male; + +import com.javarush.task.task37.task3702.Human; + +/** + * Created by Archmage on 28.07.2017. + */ +public class KidBoy implements Human { + public static final int MAX_AGE = 12; + + @Override + public String toString() { + return "KidBoy{}"; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task37/task3702/male/MaleFactory.java b/4.JavaCollections/src/com/javarush/task/task37/task3702/male/MaleFactory.java new file mode 100644 index 0000000..dc50da0 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task37/task3702/male/MaleFactory.java @@ -0,0 +1,19 @@ +package com.javarush.task.task37.task3702.male; + +import com.javarush.task.task37.task3702.AbstractFactory; +import com.javarush.task.task37.task3702.Human; + +/** + * Created by Archmage on 28.07.2017. + */ +public class MaleFactory implements AbstractFactory { + public Human getPerson(int age){ + if (age <= KidBoy.MAX_AGE){ + return new KidBoy(); + }else if (age <= TeenBoy.MAX_AGE){ + return new TeenBoy(); + }else { + return new Man(); + } + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task37/task3702/male/Man.java b/4.JavaCollections/src/com/javarush/task/task37/task3702/male/Man.java new file mode 100644 index 0000000..5eb37b1 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task37/task3702/male/Man.java @@ -0,0 +1,14 @@ +package com.javarush.task.task37.task3702.male; + +import com.javarush.task.task37.task3702.Human; + +/** + * Created by Archmage on 28.07.2017. + */ +public class Man implements Human { + + @Override + public String toString() { + return "Man{}"; + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task37/task3702/male/TeenBoy.java b/4.JavaCollections/src/com/javarush/task/task37/task3702/male/TeenBoy.java new file mode 100644 index 0000000..4652a95 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task37/task3702/male/TeenBoy.java @@ -0,0 +1,15 @@ +package com.javarush.task.task37.task3702.male; + +import com.javarush.task.task37.task3702.Human; + +/** + * Created by Archmage on 28.07.2017. + */ +public class TeenBoy implements Human { + public static final int MAX_AGE = 19; + + @Override + public String toString() { + return "TeenBoy{}"; + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task37/task3702/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task37/task3702/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..4852fad --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task37/task3702/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,83 @@ +taskKey="com.javarush.task.task37.task3702.big04" + +Фабрики (4) + +1. В корне задачи создай интерфейс AbstractFactory, в который вынеси сигнатуру общего в фабриках метода. + +2. Реализуй интерфейс AbstractFactory в обеих фабриках. + +3. В корне задачи создай класс FactoryProducer, в котором создай публичный статический энум HumanFactoryType +со значениями MALE, FEMALE. + +4. В FactoryProducer создай публичный статический метод getFactory с аргументом HumanFactoryType. +Этот метод должен возвращать одну из фабрик: для ключа MALE - MaleFactory, для FEMALE - FemaleFactory. + +Молодец, Фабрика фабрик готова! Это паттерн Abstract Factory. +В коде тебе не важно, какая фабрика используется. + +Твои успехи: +1. Освоен паттерн Factory Method. +2. Освоен паттерн Abstract Factory. +3. +2 паттерна для прохождения собеседования. +Работа джава программистом стала еще ближе, скоро достигнешь цели! + + +Требования: +1. Класс MaleFactory должен поддерживать интерфейс AbstractFactory. +2. Класс FemaleFactory должен поддерживать интерфейс AbstractFactory. +3. В классе FactoryProducer должен быть создан enum HumanFactoryType со значениями MALE, FEMALE. +4. Метод getFactory в классе FactoryProducer должен принимать один параметр типа HumanFactoryType. +5. Метод getFactory в классе FactoryProducer должен возвращать одну из фабрик в зависимости от принятого параметра. + + +Фабрики (3) + +1. Создай пакет female, в котором создай KidGirl, TeenGirl и Woman аналогично классам из пакета male. + +2. Создай в пакете female фабрику FemaleFactory аналогичную MaleFactory с тем же принципом получения объектов. + +3. Подумай, что общего у двух фабрик? Что можно сделать, чтобы легко можно было переключаться между ними? +Ответ - в следующем задании. + + + +Фабрики (2) + +1. Создай публичный класс MaleFactory в пакете male с публичным методом getPerson, который принимает один параметр int age (возраст) и +возвращает нужный объект одного из классов, реализующих интерфейс Human. + +2. Логика метода getPerson: используя константу MAX_AGE определи, какой класс соответствует переданному возрасту. +Например, age=4 соответствует мальчику (KidBoy), age=15 - подростку (TeenBoy), остальной возраст - взрослому мужчине. + +3. В методе main класса Solution создай фабрику и вызови у нее метод getPerson три раза с такими параметрами: 99, 4, 15. +Выведи результат в консоль. +Вывод должен быть следующий: +Man{} +KidBoy{} +TeenBoy{} + +Молодец, Фабрика готова! Это паттерн Factory Method. + + + +Фабрики (1) + +Привет! +Сейчас ты будешь разбираться с паттерном Factory Method. Возьмем пример с людьми. +Будем определять, к какому типу относится человек в зависимости от его возраста. + +В этом задании подготовим данные, которые будем использовать в фабрике. + +1. Для всех типов людей создай общий интерфейс Human. + +2. Будем делать Factory для мужчин. Для этого создай пакет male, в котором создай классы KidBoy, TeenBoy, Man. +Во всех этих классах реализуй интерфейс Human. + +3. В каждом классе KidBoy, TeenBoy создай свою публичную константу MAX_AGE с соответствующими значениями: 12, 19. + +4. Сгенерируй автоматические методы toString для каждого класса KidBoy, TeenBoy, Man. Получится "KidBoy{}" и т.п. + +5. Создай класс Solution с методом main. + + + diff --git a/4.JavaCollections/src/com/javarush/task/task37/task3707/AmigoSet.java b/4.JavaCollections/src/com/javarush/task/task37/task3707/AmigoSet.java new file mode 100644 index 0000000..ebce865 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task37/task3707/AmigoSet.java @@ -0,0 +1,106 @@ +package com.javarush.task.task37.task3707; + +import java.io.*; +import java.util.*; + +/** + * Created by Archmage on 31.05.2017. + */ +public class AmigoSet extends AbstractSet implements Serializable, Cloneable, Set { + private final static Object PRESENT = new Object(); + private transient HashMap map; + + + @Override + public Iterator iterator() { + return map.keySet().iterator(); + } + + + @Override + public Object clone(){ + try { + HashMap newMap = (HashMap) map.clone(); + AmigoSet newAmigoSet = new AmigoSet(); + newAmigoSet.map = newMap; + return newAmigoSet; + }catch (Exception ex){ + throw new InternalError(); + } + } + + private void writeObject(ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + out.writeFloat(HashMapReflectionHelper.callHiddenMethod(map, "loadFactor")); + out.writeInt(HashMapReflectionHelper.callHiddenMethod(map, "capacity")); + out.writeInt(map.size()); + for (E entry: map.keySet()){ + out.writeObject(entry); + } + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + Float loadFactor = in.readFloat(); + int capacity = in.readInt(); + int size = in.readInt(); + map = new HashMap(capacity, loadFactor); + for (int i = 0; i < size; i++){ + map.put((E) in.readObject(), PRESENT); + } + + + } + + @Override + public boolean isEmpty() { + return map.isEmpty(); + } + + public boolean contains(Object o) { + return null != map.get((E) o); + } + + public void clear(){ + map.clear(); + } + + @Override + public boolean remove(Object o) { + return null != map.remove(o); + } + + @Override + public int size() { + return map.size(); + } + + public AmigoSet(){ + map = new HashMap<>(); + } + + public AmigoSet(Collection collection){ + map = new HashMap((16 > collection.size()/.75f ? 16 : (int)(collection.size()/.75f + 1))); + addAll(collection); + } + + @Override + public boolean add(E e) { + return null == map.put(e, PRESENT); + } + + + public static void main(String[] args) throws IOException, ClassNotFoundException { + AmigoSet amigoSet = new AmigoSet<>(); + amigoSet.add(4); + amigoSet.add(5); + + /*ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(new File("F:\\JavaProjects\\InputSource\\out.txt"))); + out.writeObject(amigoSet); + out.close();*/ + //System.out.println(amigoSet.remove(3)); + ObjectInputStream in = new ObjectInputStream(new FileInputStream(new File("F:\\JavaProjects\\InputSource\\out.txt"))); + amigoSet = (AmigoSet) in.readObject(); + System.out.println(amigoSet); + } +} diff --git a/4.JavaCollections/src/com/javarush/task/task37/task3707/HashMapReflectionHelper.java b/4.JavaCollections/src/com/javarush/task/task37/task3707/HashMapReflectionHelper.java new file mode 100644 index 0000000..5cf7740 --- /dev/null +++ b/4.JavaCollections/src/com/javarush/task/task37/task3707/HashMapReflectionHelper.java @@ -0,0 +1,17 @@ +package com.javarush.task.task37.task3707; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; + +public class HashMapReflectionHelper { + public static T callHiddenMethod(HashMap map, String methodName) { + try { + Method method = map.getClass().getDeclaredMethod(methodName); + method.setAccessible(true); + return (T) method.invoke(map); + } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ignored) { + } + return null; + } +} diff --git "a/4.JavaCollections/src/com/javarush/task/task37/task3707/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" "b/4.JavaCollections/src/com/javarush/task/task37/task3707/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" new file mode 100644 index 0000000..6bca8eb --- /dev/null +++ "b/4.JavaCollections/src/com/javarush/task/task37/task3707/\320\243\321\201\320\273\320\276\320\262\320\270\320\265.jrtc" @@ -0,0 +1,106 @@ +taskKey="com.javarush.task.task37.task3707.big06" + +AmigoSet (6) + +Открой исходники HashSet (если у тебя нет исходников джавы, то скачай их и подключи), сравни со своим кодом. +Быстро это можно сделать сравнив через буфер. Скопируй код класса HashSet в буфер. +Зайди в класс AmigoSet, далее правая кнопка мыши -> Compare with Clipboard. + +Ты только что реализовал сет, аналогичный HashSet. Теперь будешь знать, как внутри устроен HashSet. +Молодец, теперь коллекции тебе не страшны! + + +Требования: +1. Поздравляю, ты написал собственную реализацию множества и изучил HashSet во всех деталях! + + +AmigoSet (5) + +Твое собственное множество AmigoSet реализует интерфейс Serializable. Однако, не сериализуется правильно. + +1. Реализуй свою логику сериализации и десериализации. +Вспоминай, какие именно приватные методы нужно добавить, чтоб сериализация пошла по твоему сценарию. +Для сериализации: +* сериализуй сет +* сериализуй capacity и loadFactor у объекта map, они понадобятся для десериализации. +Т.к. эти данные ограничены пакетом, то воспользуйся утилитным классом HashMapReflectionHelper, чтобы достать их. + +Для десериализации: +* вычитай все данные +* создай мапу используя конструктор с capacity и loadFactor + +2. Помнишь, что такое transient? + + + +AmigoSet (4) + +Твое собственное множество AmigoSet реализует интерфейс Cloneable. Однако, не клонируется правильно. +Напиши свою реализацию метода Object clone(), сделай поверхностное клонирование. + +* Клонируй множество, клонируй map. +* В случае возникновения исключений выбрось InternalError. +* Убери лишнее пробрасывание исключения. + +Расширь модификатор доступа до public. + + + +AmigoSet (3) + +Напиши свою реализацию следующих методов при условии, что нужно работать с ключами мапы: +* Iterator iterator() - очевидно, что это итератор ключей. Получи множество ключей в map, верни его итератор +* int size() - это количество ключей в map, равно количеству элементов в map +* boolean isEmpty() +* boolean contains(Object o) +* void clear() +* boolean remove(Object o) + +Ничего своего писать не нужно, используй то, что уже реализовано для множества ключей map. +Используй Alt+Insert => Override methods + + + +AmigoSet (2) + +Изобретать механизм работы с хешем не будем, он уже реализован во многих коллекциях. +Мы возьмем коллекцию HashMap и воспользуемся ей. + +1. Создай приватную константу Object PRESENT, которую инициализируй объектом Object, это будет наша заглушка. + +2. Создай private transient поле HashMap map. Список ключей будет нашим сэтом, а вместо значений будем пихать в мапу заглушку PRESENT. +Напомню, нам нужны только ключи, а вместо значений для всех ключей будем вставлять PRESENT. Там же должно что-то быть :) +Посмотрим, что из этого получится :) + +Коллекции обычно имеют несколько конструкторов, поэтому: + +3. Создай конструктор без параметров, в котором инициализируй поле map. + +4. Создай конструктор с одним параметром Collection collection. +Для инициализации поля map воспользуйся конструктором, в который передается Capacity. +Вычисли свою Capacity по такой формуле: максимальное из 16 и (collection.size()/.75f) +Добавь все элементы из collection в нашу коллекцию. +Нужный метод добавления всех элементов у нас есть благодаря тому, что AbstractSet наследуется от AbstractCollection. + +5. Напиши свою реализацию для метода метод add(E e): добавь в map элемент 'e' в качестве ключа и PRESENT в качестве значения. +Верни true, если был добавлен новый элемент, иначе верни false. + + + +AmigoSet (1) + +Давай напишем какую-нибудь коллекцию. Пусть это будет твой собственный Set. +Пусть этот класс позволяет вставку NULL. + +1. Создай класс AmigoSet. Пусть этот класс наследуется от AbstractSet. +Этот сэт должен поддерживать интерфейсы Serializable и Cloneable (как же без этого??). +Также очевидно, что он должен реализовывать интерфейс Set. + +2. Этот класс должен работать с любыми типами, поэтому сделай его дженериком: добавь тип, например, E. +Стандартные буквы, которые используют для дженериков - это E (element), T (type), K (key), V (value). +Названия не принципиальны, но облегчают чтение кода. + +3. Воспользуйся горячими клавишами Идеи и реализуй необходимые методы, оставь реализацию по умолчанию. + + + diff --git a/5.OnlineInternship/5.OnlineInternship.iml b/5.OnlineInternship/5.OnlineInternship.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/5.OnlineInternship/5.OnlineInternship.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/5.OnlineInternship/src/Internship.info b/5.OnlineInternship/src/Internship.info new file mode 100644 index 0000000..5f803a8 --- /dev/null +++ b/5.OnlineInternship/src/Internship.info @@ -0,0 +1 @@ +Стажировка JavaRush \ No newline at end of file