Lecture
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.
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;
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
.
The Hashtable
class is one of the implementations of the Map interface. *
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
.
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.
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:
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.
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.
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.
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.”
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
.
Comments
To leave a comment
OOP and Practical JAVA
Terms: OOP and Practical JAVA