Telegram Web Link
📌 Горячие клавиши для IntelliJ IDEA (самая популярная среда для Java)

#cheatsheet #java

@javatg
📌 Шпаргалка по Maven

Maven — один из самых популярных и удобных инструментов для управления и сборки проектов на Java. Сохраняй и делись с друзьями!

#cheatsheet #java

@javatg
📌 Шпаргалка по синтаксису Java

#java #cheatsheet

@javatg
🖥 Методы equals() и hashcode() в языке Java

Метод equals() в Java
Как вы наверняка знаете, сравнение посредством == в Java сравнивает ссылки, но объекты таким образом не сравнить. Следующий пример подобного сравнения двух строк вернёт false:

public static void main(String[] args) {
//false
System.out.println(new String("Tproger") == new String("Tproger"));
}


Пусть значения и одинаковы, но переменные String указывают на разные объекты.

Тут-то в игру и вступает метод equals(), предусмотренный в Java для сравнения именно объектов. Данный метод проверяет два объекта одного происхождения на логическую равность.

То есть, сравнивая два объекта, программисту необходимо понять, эквивалентны ли их поля. При этом необязательно все поля должны быть идентичными, поскольку метод equals() подразумевает именно логическое равенство.

➡️ Читать дальше

@javatg
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 Задача c собеседования

Задан массив (или ArrayList, как вам больше нравится) целых чисел, в котором содержатся элементы Integer от 1 до 100. В этом массиве есть один и только один продублированный элемент. Как его найти?

Такие задачи для Java-программиста привычнее, чем предыдущие три. Потому что она не о знании тонкостей языка, которые почти никогда не используются, а о логике.

Первый необузданный порыв — решать перебором — пропадает довольно быстро, когда включается голова или там установка «я же программист, я же умный». Плохо только, что на собеседовании, в условиях стресса, этого может и не произойти. Так что думайте сейчас, прежде, чем заглядывать в решение!

Алгоритм решения следующий:
Посчитайте сумму всех чисел от 1 до 100. Думаем, вы знаете, как это можно сделать (например, с помощью знаменитого метода Гаусса)

Теперь считаете сумму элементов вашего массива или ArrayList’а.

И… вычитаете первую сумму из второй.

Бинго! Полученное число — и есть значение дублирующегося элемента.

Код решения java-задачи для ArrayList.

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class FindDuplicate {
private static void findDuplicate(List<Integer> elements) {
//находим сумму всех уникальных элементов списка
int distinctSum = elements.stream().distinct().mapToInt(e -> e).sum();
//находим сумму всех элементов списка
int totalSum = elements.stream().mapToInt(e -> e).sum();
System.out.println("Элемент, который повторяется : " + (totalSum - distinctSum));
}

public static void main(String[] args) {
//создаем список последовательных элементов на промежутке [1..101).
List <Integer> elements = IntStream.range(1, 101).boxed().collect(Collectors.toList());
//устанавливаем элементу с индексом 53 значение 23
elements.set(53, 23);
findDuplicate(elements);
}
}


Другое решение

import java.util.List;
import java.util.ArrayList;

public class Duplicate {

public int findDuplicateNumber(List<Integer> numbers) {

int highestNumber = numbers.size() - 1;
int total = getSum(numbers);
int duplicate = total - (highestNumber * (highestNumber + 1) / 2);
return duplicate;
}

public int getSum(List<Integer> numbers) {

int sum = 0;
for (int num : numbers) {
sum = sum + num;
}
return sum;
}

public static void main(String a[]) {
List <Integer> numbers = new ArrayList <Integer>();
for (int i = 1; i < 100; i++) {
numbers.add(i);
}
//добавляем дубликат в список
numbers.add(25);
Duplicate dn = new Duplicate();
System.out.println("Элемент, который повторяется: " + dn.findDuplicateNumber(numbers));
}
}


@javatg
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 Задача c собеседования

Создание бесконечного цикла на пустом месте

Дан блок кода. Дополните его так, чтобы цикл стал бесконечным.

class ToInfinity {
public static void main(String[] args) {

//впишите код сюда

for (int i = start; i <= start + 1; i++) {
/* тут должен быть бесконечный цикл, менять ничего нельзя*/
}
}
}


«Ничего сложного», — скажете вы. Скорее всего, вы не раз попадали в такую историю: решая задачи по Java, вы создавали бесконечный цикл и думали, как от него избавиться. Тут же наоборот. Хитрость в том, что сам цикл и условия выхода из него менять нельзя. Есть только две итерации. Тем не менее, их вполне достаточно, чтобы создать бесконечный цикл.

Похоже, что он должен работать только для двух итераций, но его можно сделать бесконечным, за счет использования переполнения. Уже догадались, как?
Решение
За счёт переполнения. Integer.MAX_VALUE — максимальное значение, которое int может хранить в Java. Если вы достигаете Integer.MAX_VALUE и инкрементируете это значение, то скатываетесь к Integer.MIN_VALUE, то есть, к минимальному значению Integer. Таким образом, для решения этой Java-задачи нам достаточно присвоить переменной start значение на 1 меньшее, чем максимальное для типа данных int.

Код задачи на Java:

class ToInfinity {
public static void main(String[] args) {
int start = Integer.MAX_VALUE - 1;
for (int i = start; i <= start + 1; i++) {
//бесконечный цикл
System.out.println(i); //убеждаемся в бесконечности цикла
}
}
}

Что получается? Мы начинаем со start=2147483645 (Integer.MAX_VALUE-1), на следующей итерации значение становится 2147483645, потом 2147483646, затем -2147483648, -2147483647… и так далее.

@javatg
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 Задача c собеседования

Создайте комментарий, который будет выполнятся

Ну вот, приехали! С самых первых лекций мы слышали о том, что комментарии не выполняются. На то они и комментарии. Думаем, решение этой задачи для Java-программиста, даже опытного, — не всегда очевидно. Тем не менее, есть один хитрый способ, как заставить Java-машину «легально» запустить комментарий на выполнение. Чувствуете, откуда ветер дует? Попробуйте предположить!
Решение

Код решения задачи на Java:

public class ExecutableComment {
public static void main(String[] args) {
// комментарий ниже будет выполнен!
// \u000d System.out.println("выполняемый комментарий");
}
}


Если набрать код этой задачи по джава в IDE, вот что мы получим:

выполняемый комментарий

Причина в том, что компилятор Java считывает Unicod-символ \u000d как новую строку, и читает наш код следующим образом:

Расшифрованный компилятором код решения задачи на Java:

public class ExecutableComment {
public static void main(String[] args) {
// the line below this gives an output
// \u000d
System.out.println("comment executed");
}
}

@javatg
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 Задача c собеседования

О единственном дубликате в массиве целых чисел
Задан массив (или ArrayList, как вам больше нравится) целых чисел, в котором содержатся элементы Integer от 1 до 100. В этом массиве есть один и только один продублированный элемент. Как его найти?

Такие задачи для Java-программиста привычнее, чем предыдущие три. Потому что она не о знании тонкостей языка, которые почти никогда не используются, а о логике.

Первый необузданный порыв — решать перебором — пропадает довольно быстро, когда включается голова или там установка «я же программист, я же умный». Плохо только, что на собеседовании, в условиях стресса, этого может и не произойти. Так что думайте сейчас, прежде, чем заглядывать в решение!
Алгоритм решения следующий:
Посчитайте сумму всех чисел от 1 до 100. Думаем, вы знаете, как это можно сделать (например, с помощью знаменитого метода Гаусса)

Теперь считаете сумму элементов вашего массива или ArrayList’а.

И… вычитаете первую сумму из второй.

Бинго! Полученное число — и есть значение дублирующегося элемента.

Код решения java-задачи для ArrayList.

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class FindDuplicate {
private static void findDuplicate(List<Integer> elements) {
//находим сумму всех уникальных элементов списка
int distinctSum = elements.stream().distinct().mapToInt(e -> e).sum();
//находим сумму всех элементов списка
int totalSum = elements.stream().mapToInt(e -> e).sum();
System.out.println("Элемент, который повторяется : " + (totalSum - distinctSum));
}

public static void main(String[] args) {
//создаем список последовательных элементов на промежутке [1..101).
List <Integer> elements = IntStream.range(1, 101).boxed().collect(Collectors.toList());
//устанавливаем элементу с индексом 53 значение 23
elements.set(53, 23);
findDuplicate(elements);
}
}

Другое решение

import java.util.List;
import java.util.ArrayList;

public class Duplicate {

public int findDuplicateNumber(List<Integer> numbers) {

int highestNumber = numbers.size() - 1;
int total = getSum(numbers);
int duplicate = total - (highestNumber * (highestNumber + 1) / 2);
return duplicate;
}

public int getSum(List<Integer> numbers) {

int sum = 0;
for (int num : numbers) {
sum = sum + num;
}
return sum;
}

public static void main(String a[]) {
List <Integer> numbers = new ArrayList <Integer>();
for (int i = 1; i < 100; i++) {
numbers.add(i);
}
//добавляем дубликат в список
numbers.add(25);
Duplicate dn = new Duplicate();
System.out.println("Элемент, который повторяется: " + dn.findDuplicateNumber(numbers));
}
}

@javatg
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 Задача c собеседования

О неединственном дубликате в массиве целых чисел

Если предыдущая задачка показалась вам слишком лёгкой, то попробуйте решить следующую: дан лист целых чисел от 1 до 100. В нём есть дубликаты (больше одного). Как найти элементы, которые встречаются больше одного раза (найти сам элемент и указать, сколько раз он встречается)?
Решение
Тут логичнее всего для решения использовать такую структуру, как HashMap, поскольку она хранит данные парами «ключ-значение».

Код решения Java-задачи:

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class SomeDuplicates {
private static void findDuplicates(List<Integer> elements) {
HashMap <Integer, Integer > duplicates = new HashMap < >();
//заполняем Map duplicates значениями по принципу:
// ключ – значение элемента, значение – сколько раз он встречается
elements.forEach(e -> duplicates.put(e, duplicates.get(e) == null ? 1 : duplicates.get(e) + 1));
//из duplicates убираем все элементы, которые встретились не более 1 раза,
//и сохраняем //результат в список (для удобства обработки на следующем шаге)
List <Map.Entry <Integer, Integer> >
result = duplicates.entrySet().stream().filter(d -> d.getValue() > 1).collect(Collectors.toList());
//выводим результат для всех элементов в списке result
result.forEach(e -> System.out.println(String.format("Элемент %d встречается %d раз", e.getKey(), e.getValue())));
}

public static void main(String[] args) {
List <Integer> elements = IntStream.range(1, 101).boxed().collect(Collectors.toList());
elements.set(97, 23);
elements.set(27, 51);
elements.set(99, 23);
findDuplicates(elements);
}
}


@javatg
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 Вопросы c собеседования

Когда имеет смысл предпочесть абстрактный класс интерфейсу и наоборот?

Это продолжение предыдущих вопросов по абстрактным классам и интерфейсам. Если вы знаете, каковы их синтаксические различия, то ответ на этот вопрос не доставит вам проблем, так как именно они служат определяющим фактором принятия решения. Поскольку в опубликованный интерфейс практически невозможно добавить новый метод, в случае потенциальной необходимости доработки лучше использовать абстрактный класс. Развивать абстрактные классы в Java проще, чем интерфейсы. Аналогично, если в интерфейсе слишком много методов и реализация их всех становится настоящей головной болью, лучше создать абстрактный класс для реализации по умолчанию. Этому паттерну следуют и в пакете коллекций Java, абстрактный класс AbstractList обеспечивает реализацию по умолчанию для интерфейса List.

Используйте абстрактные классы, если:
Вы хотите поделиться кодом между несколькими тесно связанными классами.

- Вы ожидаете, что классы, которые расширяют ваш абстрактный класс, имеют много общих методов или полей, или требуют других модификаторов доступа, кроме public (например, protected и private).

- Вы хотите объявить нестатические или не-final поля. Это позволяет вам определять методы, которые могут получить доступ и изменить состояние объекта, которому они принадлежат.

Используйте интерфейсы, если:

- Вы ожидаете, что несвязанные классы будут реализовывать ваш интерфейс. Например, интерфейсы Comparable и Cloneable реализуются многими несвязанными классами.

- Вы хотите определить поведение конкретного типа данных, но вам не важно, кто его реализует.

- Вы хотите использовать множественное наследование типа.

@javatg
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 Типы операций обновления в MongoDB с использованием Spring Boot

Когда я начинал работать с MongoDB и Java, мне часто приходилось сталкиваться с трудностями при выборе правильной операции обновления из различных методов, предоставляемых MongoDB. Даже во время код-ревью я получал комментарии от рецензента, где мне предлагали воспользоваться, к примеру, findAndModify() вместо updateMulti().

Здесь мы обсудим различные типы операций обновления в MongoDB и то, чем они отличаются друг от друга. Я буду использовать Java 8 с фреймворком SpringBoot и реализовывать пользовательские сценарии, которые можно найти на Github.

Мы будем оценивать все операции обновления на основе пяти параметров.

- Критерии поиска (Search Criteria).
- Значение обновления (весь документ или определение обновления).
- Возвращаемое значение (весь документ или статистика результатов обновления).
- Поведение по умолчанию, если соответствующий(е) документ(ы) не найден(ы). (вставлять/не вставлять/гибкий ответ).
- Дельта-обновление.

➡️ Читать дальше
🖥 Github

@javatg
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 Могут ли абстрактные классы в языке Java реализовывать интерфейсы? Должны ли они реализовывать все методы

Ответ

Да, абстрактные классы могут реализовывать интерфейсы с помощью ключевого слова implements. Поскольку они абстрактные, то не обязаны реализовывать все методы. Наличие абстрактного базового класса и интерфейса для объявления типа является рекомендуемой практикой.

Пример — интерфейс java.util.List и соответствующий абстрактный класс java.util.AbstractList. Поскольку AbstractList реализует все общие методы, то конкретные реализации (например, LinkedList и ArrayList) не должны реализовать все методы, как в случае, если бы они реализовали интерфейс List напрямую.

Это решение сочетает преимущество использования интерфейса для объявления типа и гибкость абстрактного класса для реализации всего общего поведения в одном месте.

В книге Джошуа Блоха «Java. Эффективное программирование» есть отличная глава на тему использования интерфейсов и абстрактных классов в Java, для лучшего понимания имеет смысл её изучить.

@javatg
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 Задача Двоичный поиск

Напишите метод, который проверяет, входит ли в массив заданный элемент или нет.
Используйте перебор и двоичный поиск для решения этой задачи.
Сравните время выполнения обоих решений для больших массивов (например, 100000000 элементов).


/*
Просто перебираем, пока не найдет.
Если ничего не найдём, вернём -1
*/
public static int bruteForce(double[] array, double key) {
for (int i = 0; i < array.length; i++) {
if (array[i] == key)
return i;
}
return -1;
}

/*
Двоичный поиск
*/
public static int binarySearchRecursively(double[] sortedArray, double key) {
return binarySearchRecursively(sortedArray, key, 0, sortedArray.length);
}

/**
* Вспомогательный метод для {@link #binarySearchRecursively(double[], double)}
*
* Будем делить отрезок пополам, но не копировать, а просто "сдвигать границы",
* и вызывать этот же метод рекурсивно. Для этого используем low и high
*
* @param sortedArray сортированный массив
* @param key искомое значение
* @param low от какого значения ищем
* @param high до какого значения ищем
* @return индекс элемента
*/
private static int binarySearchRecursively
(double[] sortedArray, double key, int low, int high) {
int middle = (low + high) / 2; // середина

if (high < low) { // больше делить нечего
return -1;
}

if (key == sortedArray[middle]) { // если нашёлся
return middle;
} else if (key < sortedArray[middle]) { // ищем в левой половине
return binarySearchRecursively(
sortedArray, key, low, middle - 1);
} else {
return binarySearchRecursively( // ищем в правой половине
sortedArray, key, middle + 1, high);
}
}

// Вспомогательный метод для тестов
private static double[] generateRandomArray(int length) {
double[] array = new double[length];
for (int i = 0; i < array.length; i++) {
array[i] = Math.random();
}
return array;
}

public static void main(String[] args) {
double[] array = generateRandomArray(100000000);
Arrays.sort(array); // нужно сначала отсортировать

/*
Строго говоря,
измерять время выполнения так не совсем корректно,
лучше использовать benchmarks
см. https://habr.com/ru/post/349914/
Но масштаб будет понятен
*/
long time = System.currentTimeMillis(); // текущее время, unix-time
bruteForce(array, 0.5);
System.out.println(System.currentTimeMillis() - time);

time = System.currentTimeMillis();
binarySearchRecursively(array, 0.5);
System.out.println(System.currentTimeMillis() - time);
}

@javatg
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 Связный список

Задача:

Напишите метод, который проверяет, входит ли в массив заданный элемент или нет.
Используйте перебор и двоичный поиск для решения этой задачи.
Сравните время выполнения обоих решений для больших массивов (например, 100000000 элементов).
Решение:

/*
Просто перебираем, пока не найдет.
Если ничего не найдём, вернём -1
*/
public static int bruteForce(double[] array, double key) {
for (int i = 0; i < array.length; i++) {
if (array[i] == key)
return i;
}
return -1;
}

/*
Двоичный поиск
*/
public static int binarySearchRecursively(double[] sortedArray, double key) {
return binarySearchRecursively(sortedArray, key, 0, sortedArray.length);
}

/**
* Вспомогательный метод для {@link #binarySearchRecursively(double[], double)}
*
* Будем делить отрезок пополам, но не копировать, а просто "сдвигать границы",
* и вызывать этот же метод рекурсивно. Для этого используем low и high
*
* @param sortedArray сортированный массив
* @param key искомое значение
* @param low от какого значения ищем
* @param high до какого значения ищем
* @return индекс элемента
*/
private static int binarySearchRecursively
(double[] sortedArray, double key, int low, int high) {
int middle = (low + high) / 2; // середина

if (high < low) { // больше делить нечего
return -1;
}

if (key == sortedArray[middle]) { // если нашёлся
return middle;
} else if (key < sortedArray[middle]) { // ищем в левой половине
return binarySearchRecursively(
sortedArray, key, low, middle - 1);
} else {
return binarySearchRecursively( // ищем в правой половине
sortedArray, key, middle + 1, high);
}
}

// Вспомогательный метод для тестов
private static double[] generateRandomArray(int length) {
double[] array = new double[length];
for (int i = 0; i < array.length; i++) {
array[i] = Math.random();
}
return array;
}

public static void main(String[] args) {
double[] array = generateRandomArray(100000000);
Arrays.sort(array); // нужно сначала отсортировать

/*
Строго говоря,
измерять время выполнения так не совсем корректно,
лучше использовать benchmarks
см. https://habr.com/ru/post/349914/
Но масштаб будет понятен
*/
long time = System.currentTimeMillis(); // текущее время, unix-time
bruteForce(array, 0.5);
System.out.println(System.currentTimeMillis() - time);

time = System.currentTimeMillis();
binarySearchRecursively(array, 0.5);
System.out.println(System.currentTimeMillis() - time);
}


@javatg
Please open Telegram to view this post
VIEW IN TELEGRAM
📌 Шпаргалка по Generic-типам Java

#java #cheatsheet
🖥 Задача. Напишите Java-программу для проверки является ли введенное число - числом Армстронга.

Прежде всего, нам нужно понять, что такое число Армстронга. Число Армстронга это число, значение которого равно сумме цифр, из которых оно состоит, возведенных в степень, равную количеству цифр в этом числе. Как пример - число 371:

371 = 3*3*3 + 7*7*7 + 1*1*1 = 27 + 343 + 1 = 371

Если у вас число четырехзначное:

8208 = 8*8*8*8 + 2*2*2*2 + 0*0*0*0 + 8*8*8*8 = 4096 + 16 + 0 + 4096 = 8208

Выполняя решение, для начала мы объявляем целочисленные переменные tempNumber, x и y. Мы инициализировали переменную y значением 0. Затем мы создаем переменную qurentNumber и присваиваем ей целочисленное значение, которое мы собираемся проверить является ли оно числом Армстронга (в нашем случае это 371). Затем мы присвоили нашей переменной tempNumber то значение, которое хранится в проверяемой переменной qurentNumber.

Далее в цикле while мы переменной a присваиваем остаток от деления числа qurentNumber на 10 – и получим число единиц в изначальном числе qurentNumber. Затем мы заменяем значение переменной qurentNumber на результат деления введенного числа на 10. Нашей переменной y, значение которой изначально было установлено как 0, присваивается результат y + (x* x * x). Таким образом во время первой итерации в y попадет результат возведения в нужную степень значения числа единиц в изначальном числе, при следующей итерации в y к степени числа единиц добавится результат возведения в степень числа десятков, и так далее по всем разрядам до конца числа qurentNumber с права налево.

Наконец, мы используем оператор if-else для проверки, будет ли полученное значение переменной y равно значению переменной tempNumber (в которой хранится исходное число). Если y = tempNumber, то загаданное число является числом Армстронга, иначе - нет.

public class SeventeenthTask{


public static void main(String[] args) {

int y=0, x, tempNumber;

int qurentNumber=371; //Данное число мы будем проверять на то, является ли оно числом Армстронга

tempNumber = qurentNumber;

while(qurentNumber >0)

{

x= qurentNumber %10;

qurentNumber = qurentNumber /10;

y=y+(x*x*x);

}

if(tempNumber ==y)

System.out.println("Данное число является числом Армстронга");

else

System.out.println("Данное число не является числом Армстронга");

}

}

@javatg
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 Напишите Java-программу, чтобы найти второе по величине число в массиве.

Ответ:
В этой программе мы инициализировали массив с 10 случайными элементами, из которых мы собираемся найти второе по величине число. Далее мы создали две целочисленные переменные, которым будем присваивать значения двух целых чисел из массива - самого большого и второго по величине. Обе переменные изначально получают значения первого по индексу элемента массива. Затем мы выводим на экран все элементы, используя цикл for.
Дальнейшая логика работы программы в том, чтобы используя цикл for обойти массив.
При обходе, если элемент массива с текущим индексом больше, чем значение, хранящееся в переменной biggest, тогда переменной secondBiggest присваиваем значение, хранящееся в biggest, а переменной biggest – новое наибольшее значение в соответствии со значением текущего элемента массива. Опять же, если элемент по текущему индексу больше, чем secondBiggest, то присвойте secondBiggest значение этого элемента.
Это будет повторяться для каждой итерации и, в конечном итоге, после завершения обхода массива в цикле вы получите элементы наибольший и второй по величине элементы массива в переменных biggest и secondBiggest соответственно.
 
public class SixteenthTask {
 
public static void main(String[] args)
    {
 
        int numbersArray[] = { 10, 15, 32, 100, 16, 11, 98, 36, 95, 33 };
        int biggest= numbersArray[0];
        int secondBiggest = numbersArray[0];
        System.out.println("Полученный массив: ");
        for (int i = 0; i < numbersArray.length; i++)
        {
            System.out.print(numbersArray[i] + "\t");
        }
        for (int i = 0; i < numbersArray.length; i++)
        {
            if (numbersArray[i] > biggest)
            {
                secondBiggest = biggest;
                biggest = numbersArray[i];
            }
            else if (numbersArray[i] > secondBiggest && numbersArray[i] != biggest)
            {
                secondBiggest = numbersArray[i];
            }
        }
        System.out.println("\nВторое по величине число:" + secondBiggest);
    }
}

 
 
На экране получим:
Полученный массив: 
10     15      32      100     16      11      98      36      95      33      
Второе по величине число: 98

@javatg
Please open Telegram to view this post
VIEW IN TELEGRAM
2025/07/08 11:41:22
Back to Top
HTML Embed Code: