Чтение онлайн

ЖАНРЫ

Java: руководство для начинающих
Шрифт:

Последовательность действий

Создайте новый файл QDemo.java.

Очередь можно организовать разными способами. Мы создадим ее на основании массива, выступающего в роли хранилища данных, помещаемых в очередь. Для доступа к массиву будут использованы два индекса. Индекс размещения данных определяет, в каком месте будет размещен следующий элемент очереди. А индекс извлечения данных указывает место, откуда должен быть извлечен очередной элемент очереди. Напомним, что операция извлечения является истощающей и не позволяет извлечь один и тот же элемент дважды. Создаваемая здесь очередь предназначена для хранения символов, но та же самая логика ее организации может быть использована для размещения данных любых типов, в том числе объектов. Итак, начните

создание класса очереди Queue со следующих строк кода: class Queue { char q[]; // Массив для хранения элементов очереди int putloc, getloc; // Индексы размещения и извлечения элементов очереди }

Конструктор класса Queue создает очередь заданного размера. Его код приведен ниже.Queue(int size) { q = new char[size+1]; // выделить память для очереди putloc = getloc = 0; } Обратите внимание на то, что размер очереди оказывается на единицу больше размера, задаваемого параметром size. Особенности реализации очереди таковы, что один элемент массива остается неиспользованным, поэтому размер массива должен быть на единицу больше размера очереди, создаваемой на его основе. Первоначально индексы размещения и извлечения данных равны нулю.

Метод put , помещающий элемент в очередь, имеет следующий вид:// поместить символ в очередь void put(char ch) { if(putloc==q.length-1) { System, out .println (11 - Queue is full."); return; } putloc++; q[putloc] = ch; } Прежде всего в теле данного метода проверяется, не переполнена ли очередь. Если значение переменной putloc соответствует последнему местоположению в массиве q, то места для размещения новых элементов в очереди нет. В противном случае переменная putloc инкрементируется и новый элемент располагается в указанном месте массива. Следовательно, переменная putloc всегда содержит индекс элемента, помещенного в очередь последним.

Для извлечения элементов из очереди служит метод get , код которого приведен ниже.// извлечь символ из очереди char get { if(getloc == putloc) { System.out.println(" - Queue is empty."); return (char) 0; } getloc++; return q[getloc]; } Сначала в данном методе проверяется, пуста ли очередь. Если значения индексов в переменных getloc и putloc совпадают, то в очереди нет ни одного элемента. Именно поэтому в конструкторе Queue переменные getloc и putloc инициализируются нулевыми значениями. Если очередь не пуста, то переменная getloc инкрементируется и из нее извлекается очередной элемент. Следовательно, переменная getloc содержит индекс последнего извлеченного элемента.

Ниже приведен весь исходный код программы из файла QDemo.java. /* Пример для опробования 5.2. Класс, реализующий очередь, для хранения символов. */ class Queue { char q[]; // Массив для хранения элементов очереди int putloc, getloc; // Индексы размещения и извлечения элементов очереди Queue(int size) { q = new char[size+1]; // выделить память для очереди putloc = getloc = 0; } // поместить символ в очередь void put(char ch) { if(putloc==q.length-1) { System.out.println(" - Queue is full."); return; } putloc++; q[putloc] = ch; } // извлечь символ из очереди char get { if(getloc == putloc) { System.out.println(" - Queue is empty."); return (char) 0; } getloc++; return q[getloc]; } } // продемонстрировать класс Queue class QDemo { public static void main(String args[]) { Queue bigQ = new Queue (100); Queue smallQ = new Queue(4); char ch; int i; System.out.println("Using bigQ to store the alphabet."); // поместить буквенные символы в очередь bigQ for(i=0; i < 26; i++) bigQ.put((char) ('A' + i)); // извлечь буквенные символы из очереди bigQ и отобразить System.out.print("Contents of bigQ: "); for(i=0; i < 26; i++) { ch = bigQ.get; if(ch != (char) 0) System.out.print(ch); } System.out.println("\n"); System.out.println("Using smallQ to generate errors."); // использовать небольшую очередь smallQ для генерации ошибок for(i=0; i < 5; i++) { System.out.print("Attempting to store " + (char) ('Z' - i)); smallQ.put((char) ('Z1 - i)); System.out.println; } System.out.println; // дополнительные ошибки при обращении к очереди smallQ System.out.print("Contents of smallQ: "); for(i=0; i < 5; i++) { ch = smallQ.get; if(ch != (char) 0) System.out.print(ch); } } }

Ниже

приведен результат выполнения данной программы. Using bigQ to store the alphabet. Contents of bigQ: ABCDEFGHIJKLMNOPQRSTUVWXYZ Using smallQ to generate errors. Attempting to store Z Attempting to store Y Attempting to store X Attempting to store W Attempting to store V - Queue is full. Contents of smallQ: ZYXW - Queue is empty.

Попробуйте самостоятельно усовершенствовать класс Queue таким образом, чтобы в очереди можно было хранить другие типы данных, например значения типа int или double. Разновидность for-each цикла for

При выполнении операций с массивами очень часто возникают ситуации, когда должен быть обработан каждый элемент массива. Например, для расчета суммы всех значений, содержащихся в массиве, нужно обратиться ко всем его элементам. То же самое приходится делать при расчете среднего значения, поиске элемента и решении многих других задач. В связи с тем что задачи, предполагающие обработку всего массива, встречаются очень часто, в Java была реализована еще одна разновидность цикла for, рационализирующая подобные операции с массивами.

Вторая разновидность оператора for реализует цикл типа for-each. В этом цикле происходит последовательное обращение к каждому элементу совокупности объектов (например, массива). За последние годы циклы for-each появились практически во всех языках программирования. Изначально в Java подобный цикл не был предусмотрен и был реализован лишь в пакете JDK 5. Разновидность for-each цикла for называется также расширенным циклом for. В данной книге употребляются оба эти термина.

Ниже приведена общая форма разновидности for-each цикла for. for(тип intr_var : коллекция) блок_операторов

где тип обозначает конкретный тип intr_var — итерационной переменной, в которой сохраняются перебираемые по очереди элементы набора данных, обозначенного как коллекция. В данной разновидности цикла for могут быть использованы разные типы коллекций, но в этой книге рассматриваются только массивы. На каждом шаге цикла очередной элемент извлекается из коллекции и сохраняется в итерационной переменной. Выполнение гщкла продолжается до тех пор, пока не будут получены все элементы коллекции. Таким образом, при обработке массива размером N в расширенном цикле for будут последовательно извлечены элементы с индексами от 0 до N—1.

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

Для того чтобы стали понятнее причины, побудившие к внедрению разновидности for-each цикла for в Java, рассмотрим приведенный ниже фрагмент кода, в котором традиционный цикл for используется для вычисления суммы значений элементов массива. int nums[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; int sum = 0; for(int i=0; i < 10; i++) sum += nums[i];

Для того чтобы вычислить упомянутую выше сумму, придется перебрать все элементы массива nums от начала до конца. Перебор элементов осуществляется благодаря использованию переменной цикла i в качестве индекса массива nums. Кроме того, нужно явно указать начальное значение переменной цикла, шаг приращения и условие завершения цикла.

При использовании разновидности for-each данного цикла некоторые перечисленные выше действия выполняются автоматически. В частности, отпадает необходимость в использовании переменной цикла, задании ее исходного значения и условия завершения цикла, а также в индексировании массива. Вместо этого массив автоматически обрабатывается в цикле от начала до конца. Код, позволяющий решить ту же самую задачу с помощью разновидности for-each цикла for, выглядит следующим образом: int nums[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; int sum = 0; for(int x: nums) sum += x;

Поделиться с друзьями: