Функции для работы с массивами Java

Тип возвращаемого значения

Имя

Описание

boolean

contains(double[] array, double value)

Возвращает true, если массив содержит заданное значение.

boolean

contains(int[] array, int value)

Возвращает true, если массив содержит заданное значение.

boolean

contains(Object[] array, Object value)

Возвращает true, если массив содержит заданное значение. Объекты сравниваются с помощью метода .equals().

int

indexOf(double[] array, double value)

Возвращает индекс первого элемента массива, хранящего заданное значение. Возвращает -1, если значение не найдено или если массив пуст или не существует (равен null).

int

indexOf(int[] array, int value)

Возвращает индекс первого элемента массива, хранящего заданное значение. Возвращает -1, если значение не найдено или если массив пуст или не существует (равен null).

int

indexOf(Object[] array, Object value)

Возвращает индекс первого элемента массива, хранящего заданное значение. Объекты сравниваются с помощью метода .equals(). Возвращает -1, если значение не найдено или если массив пуст или не существует (равен null).

int

indexOfMax(double[] array)

Возвращает индекс максимального значения, содержащегося в заданном массиве.

int

indexOfMax(int[] array)

Возвращает индекс максимального значения, содержащегося в заданном массиве.

int

indexOfMin(double[] array)

Возвращает индекс минимального значения, содержащегося в заданном массиве.

int

indexOfMin(int[] array)

Возвращает индекс минимального значения, содержащегося в заданном массиве.

double

max(double[] array)

Возвращает максимальное значение, содержащееся в заданном массиве.

Выдает ошибку, если массив пуст или не существует (равен null).

double

max(int[] array)

Возвращает максимальное значение, содержащееся в заданном массиве.
Выдает ошибку, если массив пуст или не существует (равен null).

double

min(double[] array)

Возвращает минимальное значение, содержащееся в заданном массиве.
Выдает ошибку, если массив пуст или не существует (равен null).

double

min(int[] array)

Возвращает минимальное значение, содержащееся в заданном массиве.
Выдает ошибку, если массив пуст или не существует (равен null).

Массивы в Java. Курс «Программирование на Java»

В Java, чтобы объявить массив, надо в определении переменной написать квадратные скобки. Их можно разместить как перед именем переменной, так и после него. Однако первый способ предпочтительней, так как является java-стилем, второй способ – си-стиль. С правой части от знака присваивания создается объект соответствующего типа, при этом вместо круглых скобок пишутся квадратные, в которых указывается количество элементов массива. Примеры объявления переменных и создания массива вещественных чисел и строк:

double[] a = new double[10];
String[] b = new String[5];

Обращение к элементам массива происходит по их индексам, заключенным в квадратные скобки.

public class ArrayClass {
    public static void main(String[] args) {
        int[] a = new int[3];
        a[0] = 15;
        a[1] = 12;
        a[2] = -3;
 
        for (int i = 0; i < a.length; i++) {
            System.out.println(a[i]);
        }
 
        for (int i : a) {
            System.out.println(i);
        }
 
        int[][] b = new int[2][2];
        b[0][0] = -1;
        b[0][1] = 1;
        b[1][0] = 1;
        b[1][1] = -1;
 
        for (int[] ints : b) {
            for (int i : ints) {
                System.
out.println(i); } } } }

Если требуется сразу присвоить элементам массива значения, то значения перечисляются в фигурных скобках непосредственно после знака присваивания:

String[] s = {"ab", "cd", "ef"};

В Java размер обычного массива изменять нельзя.

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

import java.util.Arrays; import java.util.Random; public class ArraysTest { public static void main(String[] args) { Random random = new Random(); int[] a = new int[10]; for (int i = 0; i < 10; i++) { a[i] = random.nextInt(100); } System.out.println(Arrays.toString(a)); Arrays.sort(a); System.out.println(Arrays.toString( Arrays.copyOf(a, 5))); } }

Пример выполнения:

[22, 19, 58, 36, 45, 70, 10, 36, 91, 30]

[10, 19, 22, 30, 36]

Метод sort() сортирует переданный в качестве аргумента массив.

Метод copyOf() копирует указанное количество элементов массива. При этом создается новый массив.

Можно создавать массивы объектов собственного класса:

public class ArrayOfObjects {
    public static void main(String[] args) {
        Book[] shelf = new Book[3];
        shelf[0] = new Book("Red");
        shelf[1] = new Book("Green");
        shelf[2] = new Book("Blue");
        System.out.println(shelf[1].title);
    }
}
 
class Book {
    String title;
    Book(String title) {
        this.title = title;
    }
}

Массивы | Collections | Scala Documentation

Массивы особый вид коллекций в Scala. С одной стороны, Scala массивы соответствуют массивам из Java. Например, Scala массив

Array[Int] реализован в виде Java int[], а Array[Double] как Java double[] и Array[String] как Java String[] С другой стороны, Scala массивы дают намного больше чем их Java аналоги. Во-первых Scala массивы могут быть обобщены (generic). То есть вы можете описать массив как Array[T], где T дополнительный параметр-тип массива или же абстрактный тип. Во-вторых, Scala массивы совместимы со списками (Seq) Scala — вы можете передавать Array[T] на вход туда, где требуется Seq[T]. Ну и наконец, Scala массивы также поддерживают все операции, которые есть у списков. Вот пример:

scala> val a1 = Array(1, 2, 3)
a1: Array[Int] = Array(1, 2, 3)
scala> val a2 = a1 map (_ * 3)
a2: Array[Int] = Array(3, 6, 9)
scala> val a3 = a2 filter (_ % 2 != 0)
a3: Array[Int] = Array(3, 9)
scala> a3.reverse
res0: Array[Int] = Array(9, 3)

Учитывая то что Scala массивы соответствуют массивам из Java, каким же образом реализованы остальные дополнительные возможности массивов в Scala? Реализация массивов в Scala постоянно использует неявные преобразования. В Scala массив не пытается притворяться последовательностью. Он и не может, потому что тип данных лежащий в основе массива не является подтипом Seq. Вместо этого, используя “упаковывание”, происходит неявное преобразование между массивами и экземплярами класса scala.collection.mutable.ArraySeq, который является подклассом Seq. Вот как это работает:

scala> val seq: collection.Seq[Int] = a1
seq: scala.collection.Seq[Int] = ArraySeq(1, 2, 3)
scala> val a4: Array[Int] = seq.toArray
a4: Array[Int] = Array(1, 2, 3)
scala> a1 eq a4
res1: Boolean = false

Пример выше показывает, что массивы совместимы с последовательностями, потому как происходит неявное преобразование из массивов в ArraySeqы. Чтобы перейти обратно от ArraySeq к Array, можно использовать метод toArray, описанный в Iterable. Последняя строка в консоле показывает, что упаковка и затем распаковка с помощью toArray создает копию исходного массива.

Существует еще одно неявное преобразование, которое применяется к массивам. Такое преобразование просто “добавляет” все методы последовательностей (Seq) к массивам, но не превращает сам массив в последовательность. “Добавление” означает, что массив обернут в другой объект типа ArrayOps, который поддерживает все методы последовательности. Объект ArrayOps недолговечный, обычно он недоступен после обращения к методу последовательности и он может быть удален. Современные виртуальные машины могут избегать создания такого промежуточного объекта.

Разница между двумя неявными преобразованиями на массивах показана в следующем примере:

scala> val seq: collection.Seq[Int] = a1
seq: scala.collection.Seq[Int] = ArraySeq(1, 2, 3)
scala> seq.reverse
res2: scala.collection.Seq[Int] = ArraySeq(3, 2, 1)
scala> val ops: collection.ArrayOps[Int] = a1
ops: scala.collection.ArrayOps[Int] = [email protected]
scala> ops. reverse
res3: Array[Int] = Array(3, 2, 1)

Вы видите, что вызов reverse на seq, который является ArraySeq, даст снова ArraySeq. Это логично, потому что массивы — это Seqs, и вызов reverse на любом Seq даст снова Seq. С другой стороны, вызов reverse на экземпляре класса ArrayOps даст значение Array, а не Seq.

Пример ArrayOps, приведенный выше искусственный и используется лишь, чтоб показать разницу с ArraySeq. Обычно, вы никогда не создаете экземпляры класса ArrayOps. Вы просто вызываете методы Seq на массиве:

scala> a1.reverse
res4: Array[Int] = Array(3, 2, 1)

Объект ArrayOps автоматически вставляется через неявное преобразование. Так что строка выше эквивалентна

scala> intArrayOps(a1).reverse
res5: Array[Int] = Array(3, 2, 1)

где intArrayOps — неявное преобразование, которое было вставлено ранее. В связи с этим возникает вопрос, как компилятор выбрал intArrayOps вместо другого неявного преобразования в ArraySeq в строке выше. В конце концов, оба преобразования преобразуют массив в тип, поддерживающий метод reverse. Ответ на этот вопрос заключается в том, что два неявных преобразования имеют приоритет. Преобразование ArrayOps имеет больший приоритет, чем преобразование ArraySeq. Первый определяется в объекте Predef, а второй — в классе scala.LowPriorityImplicits, который Predef наследует. Неявные преобразования в дочерних классах и дочерних объектах имеют более высокий приоритет над преобразованиями в базовых классах. Таким образом, если оба преобразования применимы, выбирается вариант в Predef. Очень похожая схема используется для строк.

Итак, теперь вы знаете, как массивы могут быть совместимы с последовательностями и как они могут поддерживать все операции последовательностей. А как же обобщения? В Java нельзя написать T[], где T является параметром типа. Как же представлен Scala Array[T]? На самом деле обобщенный массив типа Array[T] может быть любым из восьми примитивных типов массивов Java byte[], short[], char[], int[] , long[] , float[], double или может быть массивом объектов. Единственным общим типом, включающим все эти типы, является AnyRef (или, равнозначно java.lang.Object), так что это тот тип в который компилятор Scala отобразит Array[T]. Во время исполнения, при обращении к элементу массива типа Array[T], происходит последовательность проверок типов, которые определяют тип массива, за которыми следует подходящая операция на Java-массиве. Эти проверки типов замедляют работу массивов. Можно ожидать падения скорости доступа к обобщенным массивам в три-четыре раза, по сравнению с обычными массивами или массивами объектов. Это означает, что если вам нужна максимальная производительность, вам следует выбирать конкретные массивы, вместо обобщенных. Отображать обобщенный массив еще пол беды, нам нужен еще способ создания обобщенных массивов. Это куда более сложная задача, которая требует, от вас, небольшой помощи. Чтобы проиллюстрировать проблему, рассмотрим следующую попытку написания обобщенного метода, который создает массив.

// это неправильно!
def evenElems[T](xs: Vector[T]): Array[T] = {
  val arr = new Array[T]((xs.length + 1) / 2)
  for (i <- 0 until xs.length by 2)
    arr(i / 2) = xs(i)
  arr
}

Метод evenElems возвращает новый массив, состоящий из всех элементов аргумента вектора xs, находящихся в четных позициях вектора. В первой строке тела evenElems создается результирующий массив, который имеет тот же тип элемента, что и аргумент. Так что в зависимости от фактического типа параметра для T, это может быть Array[Int], или Array[Boolean], или массив некоторых других примитивных типов Java, или массив какого-нибудь ссылочного типа.

Тут нужно немного помочь компилятору, указав какой в действительности тип параметра evenElems. Это указание во время исполнения принимает форму манифеста класса типа scala.view.ClassTag. Манифест класса — это объект дескриптор типа, который описывает, какой тип у класса верхнего уровня. В качестве альтернативы манифестам классов существуют также полные манифесты типа scala.Refect.Manifest, которые описывают все аспекты типа. Впрочем для создания массива требуются только манифесты класса.

Компилятор Scala автоматически создаст манифесты классов, если вы проинструктируете его на это. “Инструктирование” означает, что вы требуете манифест класса в качестве неявного параметра, как в примере:

def evenElems[T](xs: Vector[T])(implicit m: ClassTag[T]): Array[T] = ...

Используя альтернативный и более короткий синтаксис, вы также можете потребовать, чтобы тип приходил с манифестом класса, используя контекстное связывание (context bound). Это означает установить связь с типом ClassTag идущим после двоеточия в описании типа, как в примере:

import scala.reflect.ClassTag
// так будет работать
def evenElems[T: ClassTag](xs: Vector[T]): Array[T] = {
  val arr = new Array[T]((xs.length + 1) / 2)
  for (i <- 0 until xs.length by 2)
    arr(i / 2) = xs(i)
  arr
}

Обе показанные версии evenElems означают одно и то же. Что бы не случилось, когда построен Array[T], компилятор будет искать манифест класса для параметра типа T, то есть искать неявное значение (implicit value) типа ClassTag[T]. Если такое значение найдено, то этот манифест будет использоваться для построения требуемого типа массива. В противном случае вы увидите сообщение об ошибке, такое же как мы показывали выше.

Вот некоторые примеры из консоли, использующие метод evenElems.

scala> evenElems(Vector(1, 2, 3, 4, 5))
res6: Array[Int] = Array(1, 3, 5)
scala> evenElems(Vector("this", "is", "a", "test", "run"))
res7: Array[java.  В данном случае `evenElems` требует наличия класса манифеста для параметра типа `U`, однако ни одного не найдено. Чтоб решить такую проблему, конечно, необходимо запросить манифест от неявного класса `U`. Поэтому следующее будет работать:

scala> def wrap[U: ClassTag](xs: Vector[U]) = evenElems(xs)
wrap: [U](xs: Vector[U])(implicit evidence$1: scala.reflect.ClassTag[U])Array[U]

Этот пример также показывает, что контекстное связывание с U, является лишь сокращением для неявного параметра, названного здесь evidence$1 типа ClassTag[U].

Подводя итог, можно сказать, что для создания обобщенных массивов требуются манифесты классов. Поэтому при создании массива параметризированного типом T, вам также необходимо предоставить неявный класс манифест для T. Самый простой способ сделать это — объявить параметр типа ClassTag с контекстной привязкой, как [T: ClassTag].

Массивы.

Часть 3 – многомерные массивы.

В Java многомерные массивы представляют собой массивы массивов.

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

int

twoD[][] = new int[4][5];

Этот оператор распределяет память для массива размерностью 4×5 и присваивает ссылку на  него переменной twoD. Внутренне эта матрица реализована как массив массивов значений типа int. С точки зрения логической организации этот массив будет выглядеть так:

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

Допустим, вы хотите представить таблицу умножения в виде многомерного массива:

int

[][] multiplicationTable;

Каждая пара квадратных скобок представляет одно измерение, поэтому данный массив является двухмерным. Чтобы получить доступ к одиночному элементу int двухмерного массива, нужно указать два значения индекса, по одному для каждого измерения. Если допустить, что данный массив был задан как таблица умножения, то значение int, находящееся в любом элементе, есть произведение этих индексов. Таким образом, значение products[2][4]  равно 8, а значением products[3][7]  будет 21.

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

int

[][] multiplicationTable = new int[10][10];

В некоторых языках такой массив создается в виде единого блока из 100 значений int. Java поступает иначе. Эта строка кода выполняет три действия:

  • Объявляет переменную с именем multiplicationTable, которая содержит ссылку на массив ссылок, которые в свою очередь будут указывать на массивы int.
  • Создает массив из 10 элементов (первый индекс), который будет содержать ссылки на 10 одномерных массивов int. Вот от сюда собственно и понятие – массив массивов.
    На этой стадии создания массив ссылок заполняется значениями по умолчанию, то есть значениями null.
  • Создает еще 10 массивов, каждый из которых в свою очередь является массивом из 10 элементов int. Присваивает ссылки на каждый из этих 10 новых массивов элементам массива, созданного на втором шаге. По умолчанию каждый элемент int каждого из этих 10 новых массивов получает значение 0.

Другими словами, представленную выше строку кода, можно записать так:

int

[][] multiplicationTable = new int[10][]; // первый индекс содержит ссылки на массивы int
   for (int i = 0; i < 10; i++)
       multiplicationTable[i] = new int[10]; // создаем 10 массивов int

Графически это можно изобразить так:

Очень важно понять, что каждый из массивов с элементами int, располагаются в памяти непрерывным куском, но где и как расположены каждый из них это определяет виртуальная машина java. Исходя из этого есть рекомендация, что наружные (левые) размерности массива лучше делать меньше, а самые больше размерности внутри (правее), поскольку это, во-первых, уменьшит фрагментацию памяти, а во вторых потребует гораздо меньше памяти для размещения массива. Возьмем к примеру вот такие два определения двумерных массивов:

int

[][] a = new int[10][1000];
int[][] b = new int[1000][10];

В случае массива a, количество порождаемых в памяти объектов равно 11, а в случае массива b – 1001. Создание и обслуживание каждого объекта в памяти виртуальной машины имеет свои накладные расходы, так как виртуальная машина считает ссылки для каждого объекта, хранит его атрибуты и т.д. и т.п. Таким образом массив b может занимать в памяти в полтора, а то и в два раза больше места чем массив a.

Чтобы все еще стало понятней, лучше немного попрактиковаться

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

По существу шаги 1 и 2 выполняются в 9 строке программы.

Строки 12-15 лишь выводят значения элементов первого индекса массива, где содержаться указатели на массивы значений int. Но на данный момент там еще значения null, так как им еще не были присвоены ссылки на массивы со значениями int.

После создания массивов int (строки 18-21), на третьем шаге мы видим что теперь в первом индексе, то есть в массиве содержащем ссылки на массивы int уже находятся ссылки на эти массивы.

И теперь если обратиться по обоим индексам массива multiplicationTable, то мы увидим что массивы int были заполнены значениями по умолчанию для данного типа, то есть нулями.

Ключевое слово new автоматически выполняет инициализацию элементов массива значениями по умолчанию.

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

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

То есть в Java можно объявить и более чем двумерные массивы. Например:

int

[][][] dim3D;

И тут очень важно понимать, что первый индекс данного массива, содержит массив ссылок, на второй индекс данного массива, который в свою очередь тоже содержит массив ссылок на массивы значений int.

То есть если в данном случае мы попробуем вывести на консоль значение int[1][1], то мы получим адрес ссылки, то есть примерно то же, что и на шаге 3 в предыдущем примере. И только по полному индексу int[1][1][1] мы сможем получить значение элемента массива типа int.

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

int

[][] multiplicationTable = new int[10][];
multiplicationTable[0] = 10; // ошибка компиляции

Не смотря на то что 10 является значением int, данный код не будет скомпилирован и будет выдана ошибка: cannot convert from int to int[]. Это произошло потому, что ожидается, что данный элемент массива будет хранить ссылку на объект, а не сам объект. Строка 12 в следующем примере, как раз и демонстрирует этот момент, как сделать чтобы не было ошибки.

В тоже время нижеприведенный код не вызовет ошибки компиляции, но вызовет ошибку во время исполнения: NullPointerException.

int

[][] multiplicationTable = new int[10][];
multiplicationTable[0][0] = 10; // ошибка во время исполнения

Это происходит потому, что не был создан объект, в данном случае массив int-ов. То есть мы создали массив хранящий ссылки, на массивы int-ов, но сами эти массивы мы еще не создали, поэтому обращение к несуществующему объекту вызывает данную ошибку. Строка 19 из предыдущего примера, как раз показывает пример правильного создания объектов (массивов), на которые ссылается первый индекс. Ключевое слово new, так же служит и для создания и инициализации вложенных массивов.

В последнем примере, мы создали массив ссылок, но не создали массив int-ов, поэтому к нему и не возможно обратиться. Это можно исправить следующим кодом:

int

[][] multiplicationTable = new int[10][];
multiplicationTable[0] = new int [10];
multiplicationTable[0][0] = 10; // нет ошибки

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

Как уже упоминалось в Java можно создавать массивы любой размерности:

float

[][][] globalTemperatureData = new float[360][180][100];

Если вы создаете многомерные массивы, вам необязательно указывать все измерения массива – важно задать только крайнее слева измерение или измерения. Например, разрешены такие строки:

float

[][][] globalTemperatureData = new float[360][][];
float[][][] globalTemperatureData = new float[360][180][];

Но такие варианты ошибочны:

float

[][][] globalTemperatureData = new float[360][][100]; // Ошибка!
float[][][] globalTemperatureData = new float[][180][100]; // Ошибка!

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

Подобно одномерным массивам, многомерные массивы можно инициализировать при помощи массива-литерала. Нужно просто вложить массивы в другие массивы, применяя множество вложенных фигурных скобок. Пример ниже создает массив products[5][5]:

int

[][] products = { { 0, 0, 0, 0, 0 },
                             { 0, 1, 2, 3, 4 },
                             { 0, 2, 4, 6, 8 },
                             { 0, 3, 6, 9, 12 },
                             { 0, 4, 8, 12, 16 } };

Напомню, что такой синтаксис инициализации, можно использовать только при объявлении массива или при использовании анонимного массива, то есть массива без имени:

boolean

response = bilingualQuestion( question, new String[][] {{ «Yes», «No» },{ «Oui», «Non» } } );

Поскольку в Java многомерные массивы реализуются как массивы массивов,  вы можете использовать не только прямоугольные массвы. Например:

int

[][] triangle = {{1, 2, 3, 4, 5},
                          {6, 7, 8, 9},
                          {10, 11, 12},
                          {13, 14},
                          {15}};

Приведу еще одни пример небольшой магии с массивами в Java, чтобы углубить понимание данной темы.

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

В строке 9 мы создаем и инициализируем одномерный массив. В 11 строке создаем двумерный массив. В 12 строке происходит магия. Если вы внимательно читали, все что было написано до сих пор то должны разобраться что произошло.

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

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

А пока добавлю еще немножко магии к предыдущей программе

Тут я добавил в строках 20 и 21 поясняющий вывод, что же сталось с массивами и как они выглядят после операции в строке 17.

Кроме этого были добавлены строки создания массива int-ов, для второго индекса массива twoD, то есть для индекса 1, а так же заполнения его значениями. Это строки 23-25.

Далее, строка 26, просто вывод массива twoD на консоль.

В 27 строке небольшая магия, мы присвоили ссылку на массив int-ов, которые только что создали в массиве twoD, массиву oneD.

Затем вывели содержимое массива oneD на консоль. И уже после этого адреса ссылок на массивы.

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

Теперь наша программа генерирует следующий вывод:

А теперь поколдуем немножко с не прямоугольными массивами, дабы понять тему многомерных массивов в Java еще глубже.

Это пример работы с треугольным или ступенчатым массивом. На самом деле массивы int-ов могут быть произвольной длинны.

В 16 строке мы воспользовались стандартной библиотечным методом (Arrays.deepToString) SDK для вывода многомерных массивов на консоль, но как видно из вывода, данный метод выводит любой многомерный массив в строку, разделяя его размерности квадратными скобкам, что не очень наглядно.

Затем в цикле (строки 18-23) мы выводим треугольный массив более наглядным образом.

 

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

В данной программе мы изначально имеем три массива: один одномерный и два двумерных, но с разным количеством элементов в строках – 2 и 3 соответственно.

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

В строках 31 и 32 мы колдуем с массивом three и затем выводим результат нашего шаманства на консоль.

В результате, как-бы, получаем честный треугольный массив.

Как-бы, это потому, что на самом деле последние два индекса ссылаются массивы two и one.

А честный он потому, что нам придется с ним работать уже как с треугольным, так как, например, после магии мы уже не сможем обратиться к индексу three[2][2], поскольку получим ошибку во время исполнения программы ArrayIndexOutOfBoundsException. А как-бы он потому, что работая с индексами three[1] и three[2] мы на самом деле будем работать с массивами two и one соответственно.

Теперь рассмотрим простенький пример трехмерного массива. Следующая программа создает трехмерный массив размерности 3×4×5. Затем она инициализирует каждый элемент произведением его индексов и выводит все это дело на консоль.

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

Вот такое у нас 3D

 

Ну и в завершение данного поста приведу программу сортировки двумерного массива пузырьком.

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

Данная программа может принимать аргументы из командной строки и создавать двумерные массивы заданной размерности. Если аргументы не переданы то создается массив 10х10. Затем он заполняется случайными числами, копируется в массив который будет отсортирован первым алгоритмом, сортируется, выводится на консоль, затем несортированный снова копируется для сортировки, сортируется вторым алгоритмом и выводится на консоль.

Данная программа может сгенерировать следующие выводы:

Тут приведены примеры запусков без аргументов и с аргументами из командной строки.

Как видите разница между количеством итераций и перестановок в алгоритмах различается от двух и более раз.

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

Объяснять отличие работы второго алгоритма немного ленно. Постарайтесь разобраться сами.

Если не получится и если сильно интересно, пишите вопросы в комментариях, дабы мне не тратить понапрасну время на объяснения тут.

В следующем посте разберем некоторые методы работы с массивами из стандартной библиотеки.

Работа с массивами и объектами в Azure Cosmos DB