Java associative arrays

Lecture



The notion of associative array

An associative array is a collection of pairs of elements. Each pair contains a key and a value, and the keys are not repeated. At any time, you can get the element-value associated (in a pair) with a given key. An associative array is also called a dictionary or display.

In the form of an associative array, it is convenient to store, for example, a string obtained from a database. The key will be the name of the column, and the value will be the value of this column for the resulting row.

You can take an associative array as a type of ordinary array, in which indices can be not only integers, but arbitrary objects.

Map Interface

The Map interface contains methods for working with an associative array:

size() - returns the number of elements (pairs) in the array;

containsKey(Object key) - checks if an element with the key key exists in the array;

containsValue(Object value) - checks if there is an element with value in the array;

get(Object key) - returns the value corresponding to the key key ;

put(Object key, Object value) - adds an element to the array with the key key and the value value . If an element with such a key already exists in the array, then its value simply changes;

values() - returns the values ​​of all elements of the array as a collection (i.e., the returned result is of type Collection );

remove(Object key) - removes the element with the key key , returning the value of this element (if any) and null if there was no such element;

about the elements of the associative array Map (interface Map.Entry)

clear() - clears the array;

isEmpty() - checks if the array is empty.

Each element of an associative array, described by the Map interface, has an interface type Map.Entry , which provides three basic methods:

getKey() - returns the key of the element;

getValue() - returns the value of the element;

setValue(Object value) - changes the value of an element.

The entrySet() method defined in the Map interface will allow you to get all the elements of an associative array as a set of objects of type Map.Entry .

Hashtable class

The Hashtable class is one of the implementations of the Map interface. *

about the internal organization and construction of the class Hashtable

Hashtable , like Vector , except for the size has a capacity (the size of the buffer allocated for the array elements). In addition, it is characterized by an indicator of workload - the share of the buffer, after filling which capacity is automatically increased. The constructor of Hashtable() without parameters creates an empty object with a capacity of 101 elements and a workload indicator of 0.75. To set the initial capacity and the workload indicator, you should use a constructor with two Hashtable(int capacity, float loadFactor) parameters Hashtable(int capacity, float loadFactor) .

Hashtable has a descendant - the Properties class, which instead of pairs of arbitrary objects stores pairs of lines. If in a specific task both the keys and the values ​​of the elements of an associative array must be of type String (and this happens quite often), it is more convenient to use the Properties class - you will not need to do constant type casting.

The Properties class defines the getProperty(String key) and setProperty(String key, String value) methods, which work similarly to the get() and put() methods, but taking parameters of type String .

about ordered associative arrays (SortedSet interface)

SortedMap interface

SortedMap is a successor of the Map interface, describes an associative array, the elements of which are ordered by keys. The methods provided by this interface are: firstKey() , lastKey() , subMap(Object fromKey, Object toKey) , headMap(Object toKey) , tailMap(Object fromKey) similar to SortedSet interface SortedSet . This interface is implemented, for example, in the class TreeMap . One of the constructors of this class accepts a Comparator object, through which you can define your own sorting order.

An example of working with associative arrays

It is necessary to develop a findUser(String login, String password) method findUser(String login, String password) that finds registered users in the database with a login and password password and returns a User object created based on information from this database. The method should return null if a user with the required login and password does not exist.

Let information about registered users be stored in the USERS table, which has the following structure:

  Java associative arrays

Suppose there is already an auxiliary method getNextUser() , which returns the next row of this table, and if there are no more rows, returns null. The title of this method might look like this:

Map getNextUser();

Notice that the returned result has an interface type Map , and not a particular class (for example, Hashtable ). This is a professional approach to the development of the method. Of course, inside the method there is an operation with an object of a particular class (perhaps with the same Hashtable , because the method must create the returned object, and you cannot create an object of an abstract class or interface). But, by hiding the details of its implementation and telling the rest of the program only minimally necessary information (that the returned result supports the Map interface), the method achieves greater flexibility. Subsequently, it may be decided to replace Hashtable with HashMap , and at the same time all changes will need to be made only in the body of the getNextUser() method, and not in all places of the program where it was called.

The keys of the elements of the associative array returned by the getNextUser() method are the rows that match the table column names, and the values ​​are the rows that contain the values ​​from the corresponding table cell. Suppose that this method also makes it easier for us to work: replaces the value 0 of the category column with the string "user", and the value 1 with the string "admin". The fact is that depending on the category of the user (which is encoded with a number in the database), we must create either an object of class User , or an object derived from it of class Admin .

Our method will look like this. (It makes no sense to type it, just try to figure it out. And watch the brackets!)

private User findUser(String login, string password) { Map userData = getNextUser(); while (userData != null) { if (((String)UserData.get("login")).equals(login) && ((String)UserData.get("password")).equals(password)) { if (((String)UserData.get("category")).equals("user")) return new User((String)UserData.get("name")); if (((String)UserData.get("category")).equals("admin")) return new Admin((String)UserData.get("name")); } } userData = getNextUser(); } return null; }

Notice how each time, accessing the userData associative array with the get() method and getting the value associated with the key we need, we cast it to type String .

Notice the organization of the while loop: we call the getNextUser() method until it returns getNextUser() . If, during the processing of the next set of data from the table, we find that the login and password are the same as the parameters of the method, we terminate the work of the method with the return command, returning the required object. If the return command is never called in a loop, it will mean that there is no such user in the database and the method should return null, which he does in the last line.

Wrapper classes

An object-oriented approach to describing collections gives us a number of advantages. In particular, the ability to place in the collection objects of any classes. But at the same time simple data types are deprived. We cannot create a collection of integers int or char * characters.

In order to work with simple data types as objects (and, in particular, to apply them in collections), the so-called wrappers are used. The wrapper class is built on a very simple principle: it stores within itself a field of a simple type and provides several operations for accessing this field.

The standard Java library defines eight wrapper classes — one for each simple type. Their names coincide with the names of these types, but begin with a capital letter. That is, it is Byte , Short , Long , Float , Double , Char , Boolean . The exception is a wrapper class for integers called Integer . Each class has a simple constructor that accepts a value of the appropriate type.

Integer i = new Integer(15); Boolean b = new Boolean(false);

If necessary, you can easily get the "contents" of the class using one of its methods. Automatic casting to a simple type does not occur. So, if we need to pass an int parameter to some method, and the number we need is an object of the Integer class, we need to implement an explicit conversion:

String s; сhar ch = s.charAt(i.intValue);

But now it is easy to add objects of simple types to any collection. For example:

Vector vect = new Vector(); vect.add(b); vect.add(new Double(3.14));

The Vector class in recent versions of Java allows you to pass both primitive data types to a method, automatically creating a wrapper for them.

Work with date and time

Date / time data has to be processed quite often, so all modern programming languages ​​offer a convenient mechanism for working with them in one of their libraries.

Java has developed the Date and Calendar classes for this purpose, which are compiled into the java.util package.

The Date class stores the number of milliseconds that have elapsed since January 1, 1970 (in an internal field that has a long type). A constructor without parameters of this class creates an object containing the current time (according to the system clock of the machine on which the program runs). Another constructor, with a parameter of type long, creates a Date object based on the specified number.

The getTime() method allows you to get this number, and the setTime(long newTime) method setTime(long newTime) allows you to change it.

To display the date on the screen, its internal representation must be translated into a line that is more convenient for perception. This is usually done using the SimpleDateFormat class (which is a descendant of the abstract DateFormat class), which must be imported from the java.text package. First of all, you need to create an object of this class, specifying the string defining the formatting method as a constructor parameter. For example:

SimpleDateFormat formatter = new SimpleDateFormat("dd.MM.yyyy hh:mm");

Now you should call the format() method of the created formatting object, passing as a parameter the Date object that we want to represent as a string. To display the current date, use the command:

System.out.println(formatter.format(new Date()));

At the time of this writing, the program output to the console

23.09.2007 05:51

In the line "dd.MM.yyyy hh: mm" dd means the digits of the day, MM - the digits of the month, yyyy - the digits of the year, hh - the hours and mm - the minutes. The MMMM combination would give the name of the month (in the nominative case), and yy - only the last two digits of the year. The named components may follow in any order (moreover, they are all not required to be present), and the separators between them (in the example, this is a period, a space and a colon) may be different.

The Calendar class allows you to work with a date at a higher level, separately considering the components of the date (day, month, year, etc.). It is abstract, therefore it is necessary to use one of its heirs. That is the GregorianCalendar (describing the Gregorian calendar by which we live).

You can create an object of this class containing the current date / time with a designer without parameters. In total, the GregorianCalendar class has seven designers, the most powerful of which takes six parameters:

GregorianCalendar(int year, int month, int day, int hour, int minutes, int seconds)

You can get any part of the date using the get(int field) universal method get(int field) . The integer parameter field defines the desired part of the date.

The Calendar class defines constants describing the possible variants: ERA, YEAR, MONTH, WEEK_OF_YEAR, WEEK_OF_MONTH, DAY_OF_YEAR, DAY_OF_MONTH, DAY_OF_WEEK, HOUR_OF_DAY, MINUTE, SECOND, MILLISECOND

For example, find out what day today is:

GregorianCalendar today = new GregorianCalendar(); int result = today.get(Calendar. DAY_OF_YEAR ); System.out.println(result);

Any part of the date can be changed using the set(int field, int value) method.

Exercise

Design and develop a method that determines how much time has passed since a given date. Using this method, output to the console how much time has elapsed since your birthday in an easy-to-read form, for example: “You have turned 20 years old, 3 months, 18 days, 4 hours, 5 minutes and 10 seconds.”

Random Number Generation

The java.util package describes the Random class, which is a random number generator. In fact, because of its nature, computers cannot generate true random numbers. Numbers are generated by a specific algorithm, with each successive number depending on the previous one, and the very first number depends on a certain number, called an initializer. Two sequences of "random" numbers generated from a single initializer will be the same.

The Random class has two constructors:

Random() creates a random number generator that uses the current date as the initializer (the number of milliseconds since January 1, 1970);

Random(long seed) - creates a random number generator that uses the number of seed as an initializer.

It is recommended to use the first constructor so that the generator produces different random numbers with each new program start.

From the generator, you can get random numbers of the desired type using the methods nextBoolean() , nextInt() , nextLong() , nextFloat() , nextDouble() . Real numbers are generated in the range from 0 to 1 (not including 1), and integers from the whole range of possible values. You can generate an integer in the desired range (from 0 to max-1 ) using the nextInt(int max) or nextLong(long max) method.

Finally, you can fill with random numbers a whole array (previously created) using the nextBytes(byte[] arr) method. The elements of the arr array must be of type byte .

created: 2014-12-11
updated: 2020-10-05
132853



Rating 9 of 10. count vote: 2
Are you satisfied?:



Comments


To leave a comment
If you have any suggestion, idea, thanks or comment, feel free to write. We really value feedback and are glad to hear your opinion.
To reply

OOP and Practical JAVA

Terms: OOP and Practical JAVA