Как проинициализировать поля с static в java
Перейти к содержимому

Как проинициализировать поля с static в java

  • автор:

Как проинициализировать поля с static в java

Кроме обычных методов и полей класс может иметь статические поля, методы, константы и инициализаторы. Например, главный класс программы имеет метод main, который является статическим:

public static void main(String[] args)

Для объявления статических переменных, констант, методов и инициализаторов перед их объявлением указывается ключевое слово static .

Статические поля

При создании объектов класса для каждого объекта создается своя копия нестатических обычных полей. А статические поля являются общими для всего класса. Поэтому они могут использоваться без создания объектов класса.

Например, создадим статическую переменную:

public class Program < public static void main(String[] args) < Person tom = new Person(); Person bob = new Person(); tom.displayId(); // 3 // изменяем Person.counter Person.counter = 8; Person sam = new Person(); sam.displayId(); // Person< private int id; static int counter=1; Person()< id = counter++; >public void displayId() < System.out.printf("Id: %d \n", id); >>

Класс Person содержит статическую переменную counter, которая увеличивается в конструкторе и ее значение присваивается переменной id. То есть при создании каждого нового объекта Person эта переменная будет увеличиваться, поэтому у каждого нового объекта Person значение поля id будет на 1 больше чем у предыдущего.

Так как переменная counter статическая, то мы можем обратиться к ней в программе по имени класса:

System.out.println(Person.counter); // получаем значение Person.counter = 8; // изменяем значение

Консольный вывод программы:

Id = 1 Id = 2 3 Id = 8

Статические константы

Также статическими бывают константы, которые являются общими для всего класса.

public class Program < public static void main(String[] args) < double radius = 60; System.out.printf("Radisu: %f \n", radius); // 60 System.out.printf("Area: %f \n", Math.PI * radius); // 188,4 >> class Math

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

System.out.println("hello");

out как раз представляет статическую константу класса System. Поэтому обращение к ней идет без создания объекта класса System.

Статические инициализаторы

Статические инициализаторы предназначены для инициализации статических переменных, либо для выполнения таких действий, которые выполняются при создании самого первого объекта. Например, определим статический инициализатор:

public class Program < public static void main(String[] args) < Person tom = new Person(); Person bob = new Person(); tom.displayId(); // Person< private int id; static int counter; static< counter = 105; System.out.println("Static initializer"); >Person() < id=counter++; System.out.println("Constructor"); >public void displayId() < System.out.printf("Id: %d \n", id); >>

Статический инициализатор определяется как обычный, только перед ним ставится ключевое слово static . В данном случае в статическом инициализаторе мы устанавливаем начальное значение статического поля counter и выводим на консоль сообщение.

В самой программе создаются два объекта класса Person. Поэтому консольный вывод будет выглядеть следующим образом:

Static initializer Constructor Constructor Id: 105 Id: 106

Стоит учитывать, что вызов статического инициализатора производится после загрузки класса и фактически до создания самого первого объекта класса.

Статические методы

Статические методы также относятся ко всему классу в целом. Например, в примере выше статическая переменная counter была доступна извне, и мы могли изменить ее значение вне класса Person. Сделаем ее недоступной для изменения извне, но доступной для чтения. Для этого используем статический метод:

public class Program < public static void main(String[] args) < Person.displayCounter(); // Counter: 1 Person tom = new Person(); Person bob = new Person(); Person.displayCounter(); // Counter: 3 >> class Person < private int id; private static int counter = 1; Person()< id = counter++; >// статический метод public static void displayCounter() < System.out.printf("Counter: %d \n", counter); >public void displayId() < System.out.printf("Id: %d \n", id); >>

Теперь статическая переменная недоступна извне, она приватная. А ее значение выводится с помощью статического метода displayCounter. Для обращения к статическому методу используется имя класса: Person.displayCounter() .

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

Вообще методы определяются как статические, когда методы не затрагиют состояние объекта, то есть его нестатические поля и константы, и для вызова метода нет смысла создавать экземпляр класса. Например:

public class Program < public static void main(String[] args) < System.out.println(Operation.sum(45, 23)); // 68 System.out.println(Operation.subtract(45, 23)); // 22 System.out.println(Operation.multiply(4, 23)); // 92 >> class Operation < static int sum(int x, int y)< return x + y; >static int subtract(int x, int y) < return x - y; >static int multiply(int x, int y) < return x * y; >>

В данном случае для методов sum, subtract, multiply не имеет значения, какой именно экземпляр класса Operation используется. Эти методы работают только с параметрами, не затрагивая состояние класса. Поэтому их можно определить как статические.

Инициализация статических членов данных. Статический блок. Инициализация массивов

Если в классе объявлен статический член данных, то он всегда существует в одном экземпляре, независимо от количества создаваемых объектов класса. Статический член данных может быть объявлен как член данных класса:

class MyClass <  static int d; // статический член данных класса  static float x; // статический член данных класса . >

Если статический член данных примитивного типа не инициализирован в классе, то нему присваивается значение по умолчанию. Если статический член данных есть ссылкой на объект, то нему присваивается значение null .

Ниже приведены значения по умолчанию, которые присваиваются статическим членам данных в случае отсутствия явной инициализации

static int i; // i = 0 static boolean b; // b = false static float f; // f = 0.0 static double d; // d = 0.0 static char c; // c = символ с кодом 0 static CDate objDate; // objDate = null

Если нужно осуществить явную инициализацию статического члена данных в месте его объявления, тогда это осуществляется точно так же как и для нестатического члена данных:

class MyClass < static int d = 25; // инициализация статического члена данных конкретным значением static float x = 108.35; . >

Более подробно работа со статическими членами данных в Java освещается в теме:

2. Пример инициализации статических членов данных класса. Инициализация статического члена данных с помощью метода

В примере объявляется два класса с именами CDate и CStaticData . В классе CStaticData статические члены данных класса инициализируются так же как и нестатические члены данных класса.

// инициализация статических членов данных класса public class CStaticData < // инициализация статических членов класса  static int i = 2588;  static boolean b = true;  static float f = 3.23f;  static double d = -10.2093; // инициализация статического объекта (экземпляра) класса  static CDate objDate = new CDate(); // инициализация статического члена класса с помощью метода класса GetPi()  static double Pi = GetPi(); // метод GetPi() класса также может быть статическим  static double GetPi() < return 3.1415; >  public static void main(String[] args) < CStaticData obj = new CStaticData(); obj.b = false; CStaticData.d = -10.223; > >

Как видно из примера, чтобы инициализировать статический член данных класса Pi с помощью метода GetPi() , этот метод может быть также объявлен как статический.

3. Какой порядок инициализации, если в классе объявляются статические и нестатические члены данных класса?

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

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

public class CDataInit < // внутренние функции, которые используется при инициализации  int GetInt(String s) < System.out.println("Non-static initialization of " + s);  return 100; >  static int GetIntStatic(String s) < System.out.println("Static initialization of " + s);  return 5; > // переменные, которые должны быть инициализированы - объявлены в произвольном порядке  int i1 = GetInt("i1");  static int si1 = GetIntStatic("si1");  int i2 = GetInt("i2");  int i3 = GetInt("i3");  static int si2 = GetIntStatic("si2");  int i4 = GetInt("i4");  static int si3 = GetIntStatic("si3");  public static void main(String[] args) < CDataInit obj = new CDataInit(); > >

После объявления объекта класса CDataInit выводятся следующие строки:

Static initialization of si1 Static initialization of si2 Static initialization of si3 Non-static initialization of i1 Non-static initialization of i2 Non-static initialization of i3 Non-static initialization of i4

Как видно из приведенного выше результата, первыми инициализируются статические члены данных.

4. Что такое статический блок? Общая форма

Статический блок – это специальная конструкция, которая помогает сгруппировать несколько действий, предназначенных для инициализации статических членов данных.

Общая форма статического блока:

static < // операции, которые инициализируют статические члены класса // . >

В классе статический блок выглядит приблизительно следующим образом:

class ClassName < .  static < // инициализация статических членов данных класса // . > . >
5. Пример использования статического блока

В классе CDataInit объявляется статический блок, в котором инициализируются статические переменные a , b , c , d .

public class CDataInit <  static int a, b, c, d; // инициализация с помощью статического блока  static <  a = 1;  b = 2;  c = 3;  d = 4; >  public static void main(String[] args) < CDataInit obj = new CDataInit();  int t; // проверка t = obj.a; // t = 1 t = obj.b; // t = 2 t = obj.c; // t = 3 t = obj.d; // t = 4 > >
6. Сколько раз вызывается статический блок? В каких случаях вызывается статический блок?

Статический блок вызывается только один раз в одном из двух случаев:

  • при первом создании объекта этого класса;
  • при первом обращении к статическим членам этого класса.

Пример. Пусть задан класс CDataInit , который содержит объявление статических членов с именами a , b , c , d .

public class CDataInit <  static int a, b, c, d; // инициализация с помощью статического блока  static <  a = InitMethod("a color: #0000ff;"> b = InitMethod("b color: #0000ff;"> c = InitMethod("c color: #0000ff;"> d = InitMethod("d color: #993366;"> static int InitMethod(String s) < System.out.println(s + "100");  return 100; >  public static void main(String[] args) < // создание объекта - вызывается статический блок CDataInit obj = new CDataInit(); CDataInit obj2 = new CDataInit(); // второй раз статический блок не вызывается > >

В результате выполнения этого кода, будет выведен результат:

a = 100 b = 100 c = 100 d = 100

Как видно, в функции main() создается два объекта, а инициализированные данные выводятся только один раз. Это подтверждает правило, которое гласит: статические члены данных инициализируются в классе только один раз.

Если в функции main() вместо строки

CDataInit obj = new CDataInit();

ввести код обращения к статической переменной, например

CDataInit.a = 25;

то также будет вызван статический блок инициализации, но только один раз.

7. Инициализация массивов в классе. Как в классе инициализировать массив значениями?

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

  • непосредственным присваиванием значений массива. В этом случае в фигурных скобках задается набор значений, которые присваиваются массиву;
  • присваиванием ссылки на другой массив. В этом случае присваивается ссылка на другой массив с помощью оператора присваивания ‘=’ .
8. Пример инициализации одномерных массивов в классе

Объявляется класс CInitArray , в котором объявляются массивы a , x и ссылки на них с именами b , y .

public class CInitArray < // инициализация массива в классе // вариант 1 - непосредственная инициализация значениями  int[] a = < 1, 2, 4, 9, -8, 13, 7 >; // в массиве 7 элементов  double x[] = < -1.33, 2.905, 1.308, 10.301, 8 >; // в массиве 5 элементов // вариант 2 - присваивание ссылки  int[] b = a; // массив b ссылается на одно и то же место что и массив a  double[] y = x; // массив y ссылается на x  public static void main(String[] args) < CInitArray M = new CInitArray();  int len; // проверка длины каждого из массивов len = M.a.length; // len = 7 len = M.x.length; // len = 5 // проверка конкретных значений массивов  int d;  double f; d = M.a[3]; // d = 9 f = M.x[2]; // f = 1.308 d = M.b[3]; // d = 9 len = M.b.length; // len = 7 f = M.y[0]; // f = -1.33 len = M.y.length; // len = 5 // изменение в ячейке массива a приводит к изменению в ячейке массива b и наоборот M.a[2] = 100; d = M.b[2]; // d = 100 M.b[0] = -11; d = M.a[0]; // d = -11 // так же, изменение в ячейке массива x приводит к изменению в ячейке массива y, и наоборот M.x[3] = 1.75; f = M.y[3]; // f = 1.75 M.y[1] = -3.22; f = M.x[1]; // f = -3.22 > >

Массивы a , x инициализируются начальными значениями с использованием фигурных скобок. После этого длина массивов есть неизменной.

Массивы b и y класса инициализируются значениями, которые есть в массивах a , x . Вернее, массивы b и y ссылаются на ячейки массивов a , x .

В функции main() тестируется длина каждого массива и значения элементов массива. Длину каждого массива можно определить с помощью свойства length .

9. Пример инициализации двумерного массива в классе

Инициализация двумерного массива осуществляется точно также как и одномерного.

public class CInitArray < // инициализация двумерного массива в классе // вариант 1 - непосредственная инициализация значениями // объявляется двумерный массив aa размером 4*3  int[][] aa = < < 1, 2, 5 >, < 3, 8, 9 >, < 4, 11, -7 >, < 2, 2, 0 >>; // вариант 2 - присваивание ссылки  int[][] bb = aa; // bb ссылается на aa  public static void main(String[] args) < CInitArray M = new CInitArray();  int len, d; // проверка длин массивов len = M.aa.length; // len = 4 - количество строк len = M.aa[0].length; // len = 3 - количество столбиков в строке с индексом 0 // проверка значений d = M.aa[0][2]; // d = 5 // изменение в ячейке массива a приводит к изменению в ячейке массива b, и наоборот M.aa[0][2] = 13; d = M.bb[0][2]; // d = 13 M.bb[1][0] = 25; d = M.aa[1][0]; // d = 25 > >

Связанные темы

  • Инициализация переменных в методах класса. Инициализация членов данных класса. Способы инициализации членов данных класса
  • Применение классов в программах на Java. Определение класса и объекта класса. Примеры

Все о нестатических блоках инициализации в Java

Сегодня мы поговорим о возможножности инициализировать поля во время создания объекта с помощью нестатических блоков инициализации.

[Данная статья подготовлена на основе материала из книги OCP Oracle Certified Professional Java SE 17 Developer (Exam 1Z0-829) Programmer’s Guide, опубликованной издательством Oracle Press. — Ред.]

  • Инициализирующие выражения
  • Статические блоки инициализации
  • Нестатические блоки инициализации

Java также позволяет определять в классе статические блоки инициализации (static initializer blocks). Эти блоки могут содержать произвольный код, но в основном они используются для инициализации статических полей. Код в статическом блоке инициализации выполняется единожды, когда класс загружается в память.

Подобно тому, как статические блоки инициализации могут использоваться для инициализации статических полей именованного класса, Java предоставляет возможность инициализации полей во время создания объекта с помощью нестатических блоков инициализации (instance initializer blocks), о чем и пойдет речь в этой статье.

Во время создания объекта логика нестатических блоков инициализации выполняется перед логикой конструктора. Синтаксис нестатических блоков инициализации такой же, как и синтаксис обычных локальных блоков, что вы можете видеть в строке (2) кода примера, приведенного ниже. Код в локальном блоке выполняется каждый раз, когда создается инстанс этого класса.

class InstanceInitializers < long[] squares = new long[10]; // (1) // . < // (2) Нестатический блок инициализации for (int i = 0; i < squares.length; i++) squares[i] = i*i; >// . >

Сначала в строке (1) создается массив заданной длины под названием squares, а затем при создании каждого инстанса класса InstanceInitializers в строке (2) выполняется определенный нами нестатический блок инициализации. Обратите внимание, что этот блок инициализации не заключен в тело какого-либо метода этого класса. Класс может иметь несколько нестатических блоков инициализации, и они (а также любые инициализирующие выражения в объявлениях полей класса) будут выполняться в том порядке, в котором они определены.

Порядок объявления нестатических блоков инициализации

Аналогично другим инициализаторам, о которых мы упоминали ранее, нестатический блок инициализации не может использовать опережающую ссылку (forward reference) на поле просто по его имени в операциях чтения, поскольку это нарушает правило «объявление переменной всегда предшествует ее использованию» (declare-before-reading). Однако мы без проблем можем использовать для доступа к полю ключевое слово this.

Листинг 1 демонстрирует класс с нестатическим блоком инициализации в строке (1), который содержит опережающие ссылки на поля i, j и k, объявленные в строках (7), (8) и (9) соответственно. Доступ к этим полям в операциях чтения в строках (3), (4), (5) и (6) осуществляется с помощью this. Использование голого имени этих полей в строках (3), (4), (5) и (6) для доступа к их значениям нарушит упомянутое выше правило, что приведет к ошибке компиляции независимо от того, объявлены ли поля с применением инициализирующих выражений или являются final.

В строке (2) доступ к полям i и j осуществляется просто по имени, что разрешено в операциях записи. Однако нам нужно внимательно следить за правильностью инициализации полей. В строках (3), (4) и (5) поля i и j имеют значение 10. Однако после выполнения инициализирующих выражений в объявлениях полей значение j станет равным 100.

Листинг 1. Доступ к полям с помощью ключевого слова this

public class InstanceInitializersII < < // Нестатический блок инициализации с опережающими ссылками. (1) i = j = 10; // (2) Это разрешено. int result = this.i * this.j; // (3) i = 10, j = 10. System.out.println(this.i); // (4) 10 System.out.println(this.j); // (5) 10 System.out.println(this.k); // (6) 50 >// Объявления полей. int i; // (7) Объявление поля без инициализирующего выражения. int j = 100; // (8) Объявление поля с инициализирующим выражением. final int k = 50; // (9) Final поле с константным выражением. >

Листинг 2 иллюстрирует еще несколько тонкостей, касающихся нестатических блоков инициализации. В приведенном ниже коде в строке (4) происходит недопустимая опережающая ссылка, которая пытается прочитать значение поля nsf1 до его объявления. Операция чтения в строке (11) происходит после объявления, поэтому она не вызывает проблем. Опережающие ссылки, сделанные в левой части присваивания, разрешены, как показано в строках (2), (3), (5) и (7). В строках (5) и (12) вы можете увидеть объявление локальных переменных с использованием зарезервированного слова var.

Листинг 2. Нестатические блок инициализации и опережающие ссылки.

public class NonStaticForwardReferences < < // (1) Нестатический блок инициализации. nsf1 = 10; // (2) ОК. Присвоение nsf1 разрешено. nsf1 = sf1; // (3) OK. Доступ к статическому полю в нестатическом контексте. // int a = 2 * nsf1; // (4) Не ОК. Операция чтения до объявления. var b = nsf1 = 20; // (5) ОК. Присваивание nsf1 разрешено. int c = this.nsf1; // (6) ОК. Доступ с помощью this. >int nsf1 = nsf2 = 30; // (7) Нестатическое поле. Присвоение nsf2 разрешено. int nsf2; // (8) Нестатическое поле. static int sf1 = 5; // (9) Статическое поле. < // (10) Нестатический блок инициализации. int d = 2 * nsf1: // (11) OK. Операция чтения после объявления. var e = nsf1 = 50; // (12) OK. Присваивание nsf1 разрешено. >public static void main(String[] args) < NonStaticForwardReferences objRef = new NonStaticForwardReferences () ; System.out.println("nsf1: " + objRef.nsf1) ; System.out.println("nsf2: objRef.nsf2); >>

Ниже приведен вывод для кода из Листинга 2:

nsf1: 50 nsf2: 30

В нестатических блоках инициализации, как и в инициализирующих выражениях, для ссылки на текущий объект можно использовать ключевые слова this и super . (Оператор return же не допускается).

Нестатические блоки инициализации можно использовать для уменьшения объемов дублирования общего кода инициализации, который будет выполняться независимо от того, какой конструктор вызывается. В Листинге 3 показано, как анонимный класс, определенный в строке (1), использует для инициализации своих полей нестатический блок (строка (2)).

Листинг 3. Нестатический блок инициализации в анонимном классе

// File: InstanceInitBlock.java class Base < protected int a; protected int b; void print() < System.out.println("a: " + a); >> class AnonymousClassMaker < Base createAnonymous() < return new Base() < // (1) Анонимный класс < // (2) Нестатический блок инициализации a = 5; b = 10; >@Override void print() < super.print(); System.out.println("b: " + b); >>; // конец анонимного класса > > public class InstanceInitBlock < public static void main(String[] args) < new AnonymousClassMaker().createAnonymous().print(); >>

Ниже приведен вывод для кода из Листинга 3:

a: 5 b: 10

Обработка исключений в нестатических блоках инициализации

Обработка исключений в нестатических блоках инициализации аналогична обработке в статических блоках инициализации. Однако некоторые отличия все-таки имеются: выполнение нестатического блока инициализации может привести к возникновению не пойманного проверяемого исключения, если это исключение объявлено в блоке throws конструктора класса. Статические блоки инициализации не могут этого допустить, так как в такой инициализации класса не участвуют никакие конструкторы. Нестатические блоки инициализации в анонимных классах имеют большую степень свободы: они могут выбрасывать любые исключения.

В завершение приглашаем всех желающих на открытый урок, на котором поработаем с текстовыми файлами на примере реализации просто шифратора. На вебинаре создадим консольное приложение на Java с нуля, которое сможет шифровать и дешифровать текстовые файлы, используя очень простые алгоритмы шифрования. Записаться на открытый урок можно на странице курса «Java-разработчик».

  • java
  • инициилизация
  • нестатические блоки
  • Блог компании OTUS
  • Java

Инициализировать статическую карту в Java

В этом посте будут обсуждаться различные методы инициализации статической карты в Java.

1. Использование статического блока инициализации

В Java мы можем использовать статический блок (или статический блок инициализации) для инициализации статических полей во время загрузки класса. Это будет работать, поскольку статический блок всегда выполняется после встроенных статических инициализаторов.

import java . util . HashMap ;
import java . util . Map ;
class Main
private static final Map < Integer , String >map ;
map = new HashMap <> ( ) ;
map . put ( 1 , «one» ) ;
map . put ( 2 , «two» ) ;
public static void main ( String [ ] args ) < System . out . println ( map ) ;

Хорошей практикой является обеспечение того, чтобы статическая карта не изменялась позже в любой момент. Мы можем сделать это, создав неизменяемая карта. Идея состоит в том, чтобы обернуть изменяемую карту с помощью Collections.unmodifiableMaput() и создание неизменяемый вид исходной карты только для чтения.

import java . util . Collections ;
import java . util . HashMap ;
import java . util . Map ;
class Main
private static final Map < Integer , String >immutableMap ;
Map < Integer , String >mutableMap = new HashMap <> ( ) ;
mutableMap . put ( 1 , «one» ) ;
mutableMap . put ( 2 , «two» ) ;
immutableMap = Collections . unmodifiableMap ( mutableMap ) ;
public static void main ( String [ ] args ) < System . out . println ( immutableMap ) ;

Для создания карты с несколькими записями лучше создать типобезопасную Builder класс, как показано ниже. Затем мы можем использовать Builder put() метод, который принимает пары ключ-значение вместо карты. put() связывает ключ со значением в построенной карте.

import java . util . HashMap ;
import java . util . Map ;
class Builder < K , V >
private final Map < K , V >map ;
public Builder ( Map < K , V >map ) < this . map = map ; public Builder < K , V >put ( K k , V v )
map . put ( k , v ) ;
return this ;
class Main
private static final Map < Integer , String >map = new HashMap <> ( ) ;
new Builder <> ( map )
. put ( 1 , «one» )
. put ( 2 , «two» )
. put ( 3 , «three» )
. put ( 4 , «four» )
. put ( 5 , «five» ) ;
public static void main ( String [ ] args ) < System . out . println ( map ) ;

2. Использование статического метода

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

import java . util . Collections ;
import java . util . HashMap ;
import java . util . Map ;
class Main
private static final Map < Integer , String >immutableMap = initializeHashMap ( ) ;
private static Map < Integer , String >initializeHashMap ( )
Map < Integer , String >map = new HashMap ( ) ;
map . put ( 1 , «one» ) ;
map . put ( 2 , «two» ) ;
return Collections . unmodifiableMap ( map ) ;
public static void main ( String [ ] args ) < System . out . println ( immutableMap ) ;

3. Использование Java 8

Мы можем использовать поток Java 8 для создания статических карт, получая поток из статических фабричных методов, таких как Stream.of() или же Arrays.stream() и накопление входных элементов в новую карту с использованием collectors.

import java . util . Arrays ;
import java . util . Map ;
import java . util . stream . Collectors ;
class Main
private static final Map < String , String >map =
Arrays . stream ( new String [ ] [ ] < > ) . collect ( Collectors . toMap ( keyMapper -> keyMapper [ 0 ] ,
valueMapper -> valueMapper [ 1 ] ) ) ;
public static void main ( String [ ] args ) < System . out . println ( map ) ;

Например, для инициализации карты с разными типами ключа и значения Map , мы можем сделать что-то вроде:

import java . util . Arrays ;
import java . util . Map ;
import java . util . stream . Collectors ;
class Main
private static final Map < Integer , String >map =
Arrays . stream ( new Object [ ] [ ] < > ) . collect ( Collectors . toMap ( keyMapper -> ( Integer ) keyMapper [ 0 ] ,
valueMapper -> ( String ) valueMapper [ 1 ] ) ) ;
public static void main ( String [ ] args ) < System . out . println ( map ) ;

Другой подход, который позволяет легко использовать различные типы ключа и значения, заключается в создании потока записей карты. Есть две реализации Map.Entry интерфейс в java.util.AbstractMap : SimpleEntry а также SimpleImmutableEntry . Следующий пример демонстрирует использование AbstractMap.SimpleEntry :

import java . util . AbstractMap . SimpleEntry ;
import java . util . Map ;
import java . util . stream . Collectors ;
import java . util . stream . Stream ;
class Main
private static final Map < Integer , String >map = Stream . of (
new SimpleEntry <> ( 1 , «one» ) ,
new SimpleEntry <> ( 2 , «two» ) )
. collect ( Collectors . toMap ( SimpleEntry :: getKey , SimpleEntry :: getValue ) ) ;
public static void main ( String [ ] args ) < System . out . println ( map ) ;

4. Использование Java 9

В Java 9 очень удобно создавать экземпляры карты, предоставляя статический фабричный метод. of() на Map интерфейс, который может создать компактный немодифицируемый экземпляр Map. Например,

import java . util . Map ;
class Main
private static final Map < Integer , String >map = Map . of (
public static void main ( String [ ] args ) < System . out . println ( map ) ;

Обратите внимание, что Map.of() может поддерживать до 10 пар ключ-значение. Не существует перегрузки var-args Map.of() , который может обрабатывать любое количество отображений. Чтобы создать карту с произвольным количеством записей, мы можем использовать Map.ofEntries(Map.Entry…) .Он включает в себя перегрузку varargs, поэтому нет фиксированного ограничения на размер карты. Этот подход требует, чтобы каждая пара ключ-значение была упакована. Для упаковки ключей и значений мы можем использовать Map.Entry entry(K k, V v) .

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *