Работа со строками

Документация с полным списком возможностей String

Действия со строками (как и с любыми другими объектами) выполняются следующим синтаксисом:

  1. строка.действие(аргументы)
  2. String.действие(аргументы) (изредка бывает так)
String s = "abcdef";
sout(s.length());  // длина строки
sout(s.charAt(0)); //символ `a`, индексы с нуля. s[0]
sout(s.substring(2, 5)); //строка "cde", аналог s[2:5]
sout(s.substring(2)); //строка "cdef", аналог s[2:]
sout(s.startsWith("abc")); //true, "начинается с"
sout(s.endsWith("def")); //true
sout(s.repeat(2)); //аналог s * 2
sout(s.equals("abcdef")); // (!!!) сравнение строк
sout(s == "abcdef"); // (!!!) так нельзя

Форматирование строки

Замена ``f”Меня зовут {name}, мне {age} лет.” из python.

На java

"Меня зовут " + name + ", мне " + age + " лет."

Это может быть неудобно. Альтернатива:

String.format("Меня зовут %s, мне %d лет.", name, age).

В python аналогичная конструкция:

"Меня зовут %s, мне %d лет.".format(name, age)

%s означает, что подставляется строка

%d означает, что подставляется число в десятичной с.сч

%f означает вещественное число

Подробнее о форматах

Там же вы узнаете, как, например, просить выводить ровно две цифры после запятой: %.2f.

Операторы управления потоком исполнения

условный оператор if

см. базовый синтаксис

Цикл for

Цикл for each

Java имеет цикл for, аналогичный python:

# python
for x in list:
    print(x)

Аналог:

for (x : list) { // можно не ставить {}, т.к. одно дейстие
    sout(x);
}

Пользуйтесь в первую очередь именно этой версией цикла for. Она называется “for each”.

Классический for

Такой цикл пришел еще из языка C. Это продвинутая версия перебора диапазона значений (ср. python for i in range(10)).

Пример, самый частый вариант использования цикла:

for (int i = 0; i < 10; i++) { // можно без {}
    sout(i);
}

Это перебор чисел i от 0 до 9.

Схема работы

for (инициализатор ; условие ; итератор)
    тело
  1. Выполняется инициализатор. В примере: создается и инициализируется нулём переменная i. Кстати, переменные, введенные в иницаилизаторе, доступны только внутри цикла.
  2. Проверяем условие. Если неверно, то закончить цикл. Можно считать, что в теле цикла условие выполнено.
  3. Выполнить тело.
  4. Выполнить итератор. В примере оператор ++ увеличит на 1. Аналогично i += 1, i = i + 1.
  5. Возвращаемся к шагу 2 проверки условия.

Еще пример:

String s = "abcdef";
for (int i = 0; i < s.length(); i++)
    sout(s.charAt(i));

Здесь i всегда меньше, чем длина строки, поэтому последнее значение i это s.length() - 1.

В обратную сторону перебрать:

String s = "abcdef";
for (int i = s.length() - 1; i >= 0; i--)
    sout(s.charAt(i));

Последний пример, самый необычный, нужно только для понимания работы for:

for (int i = 0, j = 10; i < j; i++, j--)
    sout(i + " " + j); 

Распечатает:

0 10
1 9
2 8
3 7
4 6

5 5 уже не выведется, потому что для этих значений не выполнено условие i < j.

Оператор выбора switch:

Это версия оператора из времен C, она очень ограниченная и неудобная. Поэтмоу пока вы редко будете использовать такой оператор. Зато в будущих версиях java его возможности значительно увеличатся.

String name = "Ilya";
switch (name) {
    case "Николай Валентинович":
        sout("Здравствуйте, " + name);
        break;
    case "Bill Gates":
    case "Elon Mask":
        sout("Hello, " + name);
        break;
    default:
        sout("Привет, " + name);
} 

Обязательно ставится break, чтобы закончить выполнение switch, иначе выполнение идет дальше.

Функции

см. базовый синтаксис

Массивы

В Python есть списки ([10, 20, "abc]), в Java их аналогом являются тоже списки типа List.

В Java дополнительно есть массивы. Они позволяют хранить набор значений одного типа, в отличие от списков

  1. делают это очень эффективно в плане памяти;
  2. позволяют хранить значения базовых типов: int, char и т.п.
  3. доступен только ограниченный набор операций, в частности массивы имеют фиксированный размер, который не может измениться после создания массива.

Пример создания и использования массива:

int[] a = new int[3];
a[0] = 42;
a[1] = 24;
a[2] = 100;
sout(a[0] + a[2]); // 142
sout(a); // так можно, но вы увидете не содержимое массива
sout(Arrays.toString(a));

Создание массива

Создание с указанием размера

new тип[количество], например, new int[10] - это массив из 10 чисел. А new String[42] - это массив из 42 строк.

Память, выделенная для хранения массива, заполняется нулями. Это значит, что массив new int[...] будет содержать 0. new boolean[...] содержит false и т.п. для базовых типов.

Особый случай new String[...]. Массив из элементов любого объектного типа при инициализации содержит null. Это аналог None из python. Специальное значение, которое можно записать в переменную любого объектоного типа.

C null нужно быть аккуратными, потому что любое действие с null приводит к ошибке (NullPointerException):

String s = null; // отсутствие значения
sout(s.length()); // NullPointerException
sout(s.charAt(0)); // NullPointerException
if (s == null) // а вот так можно

Создание с указанием элементов

В python: [10, 20, 30] В java: new тип[]{элемент1, элемент2, ...}. Например, new int[]{10, 20, 30} или new String[]{"abc", "xyz"}.

Особый случай, если массив создается при инициализации переменной:

int[] a = new int[]{10, 20, 30};
//можно сократить до
int[] a = {10, 20, 30};
//вне инициализатора - нельзя:
Arrays.toString({10, 20, 30}) // ошибка
Arrays.toString(new int[]{10, 20, 30}) // можно

Использование массива

Доступ по индексу: a[13], это элемент с индексом 13.

Длина массива: массив.length. Без круглых скобок! (ср. с "abc".length()).

Перебор элементов массива. Если нужен индекс, например, распечатываем значения вместе с их индексом:

for (int i = 0; i < a.length; i++)
    sout(i + ": " + a[i]);

Но часто индекст не нужен, достаточно только перебрать элементы. Тогда подойдет for each цикл:

for (int x : a)
    sout(x);

Переменной x последовательно присваиваются все значения массива a. Это такой же цикл, как и в python.

Двумерные массивы. На примерах

int[][] m = new int[4][3];
m[3][2] = 42; //присвоили значение в соответсвующую ячейку.

m - это массив массивов. Он содержит 4 массива (m[0], m[1], m[2], m[3]), и каждый из них имеет 3 значения int).

int[][] m = new int[][]{
     {10, 20, 30},
     {40, 50, 60},
     {70, 80, 90},
     {100, 110, 120}
};
sout(m[3][2]); // 120
sout(Arrays.toString(m[3])); // [100, 110, 120] 

Это тоже массив размера 4 на 3.

int[][] m = new int[4][];

Это создает массив m = {null, null, null, null}

m[0] = new int[]{11, 22, 33}; // тип int[], значение было null
m[1] = new int[]{444, 555};