Массивы в Java. Создание и обработка.




_


Сегодня речь пойдёт о массивах в Java. Массивы – это та самая структура данных, без которой не обходится, пожалуй, ни одна программа. Массивы предназначены для того, чтобы хранить несколько значений в одной структуре с возможностью доступа по индексу (номеру элемента). При этом мы сможем перебирать однотипные значения в цикле. Образно можно представить себе массив как книжную полку с книгами. При этом мы всегда можем попросить Java “подать” пятую слева книгу, или последнюю. Конечно, по гибкости массивы уступают коллекциям, но по скорости они далеко впереди. Кроме того, именно в массивах можно хранить примитивные типы данных (такие как int, double и т.д.). У коллекций такой возможности нет. Коллекции могут хранить только типы данных, унаследованные от Object. Из минусов массивов можно назвать, пожалуй, только то, что после создания уже нельзя изменить его размер, хотя минус ли это?
Массивы в Java немного отличаются от массивов во многих других языках программирования. Первое, что нужно понимать, это то, что объявив переменную следующим образом:

 
	int myArray[];

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

 
	myArray = new int[10];

Вот теперь у нас есть свой, настоящий и осязаемый массив целых чисел. Можно получать его элементы по индексу, присваивать им значения и вообще делать всё, что захочется. Массив также может быть многомерным. Это как книжный шкаф с несколькими полками. Теперь чтобы указать, какую книгу мы хотим получить, нужно назвать номер полки и позицию книги на ней. Например если массив двумерный, то элементами этого массива также являются массивы. Объявить многомерный массив можно так:

 
	int myArray[][];

Не сильно отличается от одномерного. Создавать и использовать его не на много сложнее:

 
	myArray = new int[2][2];
	myArray[1][0] = 10;

Кстати, для обработки массивов (например сортировка массива) не всегда нужно писать дополнительный код. Всё уже написано до нас и проверено временем. Дело в том, что в стандартной библиотеке Java есть класс, который, порой, просто незаменим при работе с массивами. Часть рутинных операций реализована доблестными программистами Sun в его методах. Посмотрим, что же нам предлагают:

  • asList – метод, который формирует оболочку List для переданного массива.
  • binarySearch – метод выполняет бинарный поиск по массиву, переданному первым параметром, значения из второго параметра.
  • copyOf – копирует переданный массив. Вторым параметром передаём количество элементов, которое хотим получить в новом массиве.
  • copyOfRange – то же, что и copyOf, но передаём индекс начала и индекс конца области копирования.
  • deepEquals – сравнивает два массива, учитывая, что они могут быть многомерными
  • deepHashCode – высчитывает хэш массива, учитывая, что они могут быть многомерными
  • deepToString – преобразует массив в строку, учитывая, что они могут быть многомерными
  • equals – сравниват массивы
  • fill – заполняет массив одним и тем же значением, переданным вторым параметром
  • hashCode – считает хэш
  • sort – сортирует массив
  • toString – преобразует массив в строку

Замечу, что функции binarySearch, copyOf, copyOfRange, equals, fill, hashCode, sort и toString перегружены для массивов всех примитивных типов и для массивов объектов Object. В приведённо ниже примере мы будем использовать только два метода: toString и sort.
Ближе к делу. Так как сегодняшний пример посвящён массивам в Java и способам работы с ними, я выбрал задачу, которую, наверное, задают студентам всех вузов. Напишем небольшую базу данных людей. Не будем вешать на них ярлыки профессий, просто люди. Они у нас есть, нам нужно иметь возможность задать для каждого возраст, имя, распечатать список или отдельного человека и отсортировать список.
Начнём с класса, который будет содержать информацию об отдельном человеке. В нём нет ничего сложного, по этому просто приведу его код.

 
class Person {
	private String name;
	private int age;
 
	public Person(){
		this.name="";
		this.age = 0;
	}
 
	public Person(String name, int age){
		this.name=name;
		this.age = age;
	}
 
	public String getName(){
		return this.name;
	}
 
	public void setName(String name){
		this.name=name;
	}
 
	public int getAge(){
		return this.age;
	}
 
	public void setAge(int age){
		this.age = age;
	}
 
	public String toString(){
		return "<" + this.name + ", " + age + ">";
	}
}

Обращу ваше внимание на то, что мы перегрузили метод класса Object toString(). Этот метод вызывается тогда, когда требуется преобразовать значение в строковое. Теперь мы можем очень просто вывести на экран информацию о человеке, написав

 
Person p = new Person("name", 20);
System.out.println(p);

на экране увидим вот такую строку: ““.
Теперь необходим класс, в котором будет храниться список людей в массиве и который будет выполнять простейшие операции с этим списоком.

 
class SimpleDatabase {
	//Объявим наш массив
	private Person persons[];
 
	//Конструктор получает в качестве параметра размер массива
	public SimpleDatabase(int size){
		//создаём массив, дабы не получать NullPointerException при обращении к нему
		persons = new Person[size];
	}
 
	//Метод возвратит нам человека по указанному индексу
	public Person getPerson(int idx){
		//Обязательно проверяем значение индекса
		if(idx >= 0 && idx < persons.length){
			return persons[idx];
		}else{
			//Если кто-то пытается получить несуществующий элемент, выбрасываем исключение
			throw new IllegalArgumentException("Wrong index!");
		}
	}
 
	//Метод для присваивания значения элементу массива. Также проверяем индекс и кидаем исключение.
	public void setPerson(Person person, int idx){
		if(idx >= 0 && idx < persons.length){
			persons[idx] = person;
		}else{
			throw new IllegalArgumentException("Wrong index!");
		}
	}
 
	//Возвращает количество элементов в массиве.
	public int getCount(){
		return persons.length;
	}
 
	//Самый сложный метод этого класса. Будет описан чуть ниже
	public void sort(){
		Arrays.sort(persons, new Comparator<Person>(){
									//Метод сравнивает две строки, которые мы получим из toString() нашего класса Person
									public int compare(Person a1, Person a2){
										return a1.toString().compareTo(a2.toString());
									}
									//Просто возвращаем false
									public boolean equals(Object o){
										return false;
									}
								});
	}
 
	//Просто возвращаем строковое представление массива, используя метод toString()
	//класса - палочки-выручалочки Arrays
	public String toString(){
		return Arrays.toString(persons);
	}
}

Вернёмся к методу сортировки. Тут используем Arrays.sort() – этот метод и сортирует элементы массива. Но, к сожалению, по умолчанию он сортирует только примитивные типы и строки. Для того, чтобы мы могли сортировать массив объектов типа Person, есть два выхода: реализовать в этом классе интерфейс Comparable или передать в sort() объект Comparator, который сможет сравнить наших людей. Так как этот класс будет использоваться только в одном месте программы, мы не будем давать ему имя, а объявим сразу по месту требования. Давайте внимательно посмотрим на код. Выглядит так, как будто мы создаём объект интерфейса, но так на самом деле делать нельзя, по этому после new Comparator() мы опишем реализацию методов.
Теперь нам нужен класс, который предоставит пользователю интерфейс в виде меню и будет выполнять все операции с базой данных, интерпретируя команды пользователя. В этом классе нет ничего сложного, просто несколько часто встречающихся операций, по этому ограничусь комментариями в коде. Я думаю читатель со средним знанием языка программирования Java без труда разберётся в этом коде.

 
class DatabaseDriver {
	private Scanner sc;
	private SimpleDatabase db;
 
	public DatabaseDriver(){
		sc = new Scanner(System.in);
		db = new SimpleDatabase(readDatabaseSize());
	}
 
	public int readDatabaseSize(){
		while(true){
			try{
				System.out.print("Input database size: ");
				return sc.nextInt();
			}catch(InputMismatchException e){
				System.out.println("Wrong input: " + sc.next());
			}
		}
	}
 
	public void fillDatabase(){
		System.out.print("Input database data: ");
		for(int i = 0; i < db.getCount(); i++){
			Person p = new Person();
			if(sc.hasNext()){
				p.setName(sc.next());
			}else{
				p.setName("Unnamed " + i);
			}
			if(sc.hasNextInt()){
				p.setAge(sc.nextInt());
			}else{
				p.setAge(0);
			}
			db.setPerson(p, i);
		}
	}
 
	public void printDatabase(){
		System.out.println(db);
	}
 
	public void sortDatabase(){
		db.sort();
	}
 
	public void printHelp(){
		System.out.println("n+=========================== HELP ==========================+");
		System.out.println("| [setname name index] - Set NAME for person at INDEX place |");
		System.out.println("| [setage age index] - Set AGE for person at INDEX place    |");
		System.out.println("| [get index] - Print person on INDEX place                 |");
		System.out.println("| [print] - Print all persons                               |");
		System.out.println("| [sort] - Sort database                                    |");
		System.out.println("| [help] - This text                                        |");
		System.out.println("| [quit] - Close program                                    |");
		System.out.println("+===========================================================+n");
	}
 
	private Person getPerson(String param){
		try{
			return db.getPerson(Integer.valueOf(param));
		}catch(Exception e){
			System.out.println("Wrong index!");
			return null;
		}
	}
 
	private void setName(String name, String index){
		try{
			db.getPerson(Integer.valueOf(index)).setName(name);
		}catch(Throwable e){
			System.out.println("Wrong parameters!");
		}
	}
 
	private void setAge(String age, String index){
		try{
			db.getPerson(Integer.valueOf(index)).setAge(Integer.valueOf(age));
		}catch(Throwable e){
			System.out.println("Wrong parameters!");
		}
	}
 
	public void execGet(String command){
		String parts[] = command.split(" ");
		if(parts.length != 2){
			System.out.println("Wrong command format! Try help");
		}else{
			Person p = getPerson(parts[1]);
			if(p != null){
				System.out.println(p);
			}
		}
	}
 
	private void execSet(String command){
		String parts[] = command.split(" ");
		if(parts.length != 3){
			System.out.println("Wrong command format! Try help");
		}else{
			if(parts[0].equals("setname")){
				setName(parts[1], parts[2]);
			}else if(parts[0].equals("setage")){
				setAge(parts[1], parts[2]);
			}else{
				System.out.println("Unknown command: " + command);
			}
		}
	}
 
	public void startMenuMode(){
		String command = "";
		printHelp();
		sc.nextLine().trim();
		while(!command.equals("quit")){
			System.out.print("SimpleDatabase> ");
			command = sc.nextLine().trim();
 
			if(command.startsWith("set")){
				execSet(command);
			}else if(command.startsWith("get")){
				execGet(command);
			}else if(command.equals("print")){
				printDatabase();
			}else if(command.equals("sort")){
				sortDatabase();
			}else if(command.equals("help")){
				printHelp();
			}else if(command.equals("quit")){
				System.out.println("Good bye!");
			}else{
				System.out.println("Unknown command: " + command);
			}
 
		}
	}
 
}

Источник



Сайт управляется системой uCoz