Examples of Java programming thought object

Java provides a variety of ways to accommodate objects (or object handles). Let's take a look at these ways.

There are two problems that distinguish arrays from other collection types: efficiency and type. For Java, The most effective way to save and access arrays of a series of objects (actually handles to objects) is array. Array actually represents a simple linear sequence, which makes the access speed of elements very fast, but we have to pay a price for this speed: when creating an array object, its size is fixed, and it can't be in that array object Change in "time of existence". You can create an array of a specific size, and then if you run out of storage space, create a new array and move all handles from the old array to the new array. This is the behavior of the "vector" class. However, due to the high cost of flexibility in this size, we believe that the efficiency of vectors is not as high as that of arrays.

In Java, whether an array or a collection is used, a range check is performed -- if the boundary is exceeded, You will get a runtimeException error. There are several common collection classes: vector, stack and hashtable. These classes all involve the processing of objects -- as if they have no specific type. In other words, they treat them as object types (object types are the "root" of all classes in Java) Class). From a certain point of view, this method is very reasonable: we only need to build a set, Then any Java object can enter that collection (except the basic data type -- you can use Java's basic type encapsulation class to put it into the collection as a constant, or encapsulate it into your own class as a variable value). This again reflects that the array is better than the regular collection: when you create an array, you can make it accommodate a specific type.

The object array holds handles, while the basic data type array holds specific values.

1. Assemble

To accommodate a set of objects, the most appropriate choice should be an array. And if it contains a series of basic data types, it must use arrays. When we write a program, we usually don't know exactly how many objects we need in the end. Sometimes you even want to save objects in more complex ways. To solve this problem, Java provides four types of "collection classes": vector, BitSet, stack and hashtable. Compared with other languages with collection function, although the number here is quite small, they can still be used to solve an amazing number of practical problems.

These collection classes have various characteristics. For example, stack implements a LIFO (first in, first out) sequence, and hashtable is an "associative array" that allows us to associate any object. In addition, all Java collection classes can automatically change their size. Therefore, we can use a large number of objects in programming without worrying about how large the collection will be.

1.1 disadvantages: unknown type

The "disadvantage" of using java collections is the loss of type information when putting objects into a collection. This happens because when the collection was written, the programmer of that collection had no idea what type the user wanted to put into the collection. Indicating that a collection only allows specific types will prevent it from becoming a "general-purpose" tool and cause trouble for users. To solve this problem, the collection actually contains handles to some objects of type object. This type of course represents all objects in Java because it is the root of all classes. Of course, it should also be noted that this does not include basic data types, because they do not inherit from "anything". This is a good scheme, but it is not applicable to the following occasions:

(1) When putting an object handle into a collection, because the type information will be discarded, any type of object can enter our collection -- even if it is specifically indicated that it can only accommodate specific types of objects. For example, although it is indicated that it can only accommodate cats, in fact, anyone can throw a dog in.

(2) Since the type information no longer exists, the only thing a collection can be sure of is that it contains a handle to an object. Before using it formally, it must be modeled to make it have the correct type.

2、Stack

Stack can sometimes be called a "last in first out" (LIFO) set. In other words, the last thing we "push" into the stack will be the first thing to "pop up". Like all other Java sets, what we push in and pop up are "objects", so we must "shape" what we pop up 。 A rare practice is to refuse to use vector as the basic constituent element of a stack, but "inherit" a stack from vector. In this way, it has all the characteristics and behaviors of a vector, plus some additional stack behaviors. It is difficult to judge whether the designer clearly wants to do so or whether it is an inherent design.

The following is a simple stack example, which can read each row of the array and push it onto the stack as a string.

Each row of the months array enters the stack through push () inheritance and is later taken out from the top of the stack with pop (). The point to declare is that the vector operation can also be performed on the stack object. This may be determined by the characteristics of inheritance - stack "belongs to" a vector. Therefore, operations that can be performed on the vector can also be performed on the stack, such as the elementat () method.

3、Hashtable

Vector allows us to choose from a series of objects with a number, so it actually associates the number with the object. But what if we want to choose a series of objects according to other criteria? The stack is an example: its selection criterion is "the last thing pushed into the stack". This concept of "selecting from a series of objects" can also be called a "mapping", "dictionary" or "associative array". Conceptually, it looks like a vector, but instead of finding objects through numbers, it uses another object to find them! This usually belongs to an important process in a program.

In Java, this concept is embodied in the abstract class dictionary. The interface of this class is very intuitive. Size () tells us how many elements it contains; Isempty() determines whether an element is included (true if yes); put (object key, object value) adds a value (what we want) and associates it with a key (what we want to search for); get (object key) obtains the value corresponding to a key; Remove (object key) is used to delete the key value pair from the list. You can also use enumeration techniques: keys () produces an enumeration of keys; and elements () produces an enumeration of all values. This is the whole of a dictionary.

The implementation of dictionary is not troublesome. A simple method is listed below, which uses two vectors, one to hold keys and the other to hold values:

The first problem we notice in the definition of assocarray is that it "extends" the dictionary. This means that assocarray is a type of dictionary, so you can make the same request as dictionary. If you want to generate your own dictionary and do it here, all you have to do is fill in all the methods located in the dictionary (and you must override all the methods because they -- except the builder -- are abstract).

Vector key and value are linked by a standard index number. That is, if put () is called with a key of "roof" and a value of "blue" -- assuming that we are going to associate the parts of a house with their paint color, and there are 100 elements in assocarray, then "roof" will have 101 key elements and "blue" will have 101 value elements. Also, note that get (), if we pass "roof" as a key, it will generate and keys index. The index number of of () and then use that index number to generate the value in the relevant value vector.

The test in main () is very simple; It simply converts lowercase characters to uppercase characters, which can obviously be done in a more efficient way. But it shows us the power of assocarray.

The standard Java library contains only one variant of dictionary, named hashtable (hash table, annotation ③). Java's hash table has the same interface as assocarray (because both are inherited from dictionary). However, there is one aspect that reflects the difference: execution efficiency. If you think about what you must do for a get(), You'll find that searching for keys in a vector is much slower. But at this time, using hash table can speed up a lot. Instead of using lengthy linear search techniques to find a key, use a special value called "hash code". Hash code can obtain the information in an object and convert it into a "relatively unique" integer (int) of that object. All objects have a hash code, and hashcode () is a method of the root class object. Hashtable gets the hashcode () of the object and uses it to quickly find the key. In this way, the performance can be greatly improved (④). The specific working principle of hash table is beyond the scope of this book (⑤) - you only need to know that hash table is a fast "dictionary", and dictionary is a very useful tool.

③ : if you plan to use RMI (detailed in Chapter 15), you should pay attention to a problem when putting remote objects into hash tables (see core Java, published by conrell and Horstmann, Prentice Hall, 1997)

④ For example, this speed improvement still can not meet your performance requirements. You can even write your own hash table routine to further speed up the table retrieval process. This can avoid the time delay of modeling with object, and can also avoid the synchronization process built in by the hash routine of Java class library.

⑤ : the best reference book I know is practical algorithms for programmers, written by Andrew binstock and John Rex, published by Addison Wesley in 1995.

As an example of applying hash table, consider using a program to verify Java math What is the randomness of the random () method. Ideally, it should produce a perfect series of randomly distributed numbers. But to verify this, we need to generate a large number of random numbers, and then calculate how many numbers fall in different ranges. The hash table can greatly simplify this work because it can associate objects with objects (in this case, the values generated by math. Random () are associated with the number of occurrences of those values). As follows:

In main (), every time a random number is generated, it will be encapsulated in an integer object, Enables the handle to be used with the hash table (the basic data type cannot be used for a collection, only the object handle can be used). The containkey () method checks whether the key is already in the collection (that is, has the number been found before?). If it is already in the collection, the get () method obtains the value associated with the key, This is a counter object. The value I in the counter then increases by 1, indicating that this particular random number appears again.

If the key has not been found before, the method put () will still have a new key value pair built into the hash table. At the beginning of creation, counter will automatically initialize its variable I to 1, which marks the first occurrence of the random number.

To display the hash table, simply print it out. The hashtable tostring() method can traverse all key value pairs and call tostring() for each pair. Integer tostring() is defined in advance. You can see the toString used by the counter. The results of one run (with some line breaks added) are as follows:

You may wonder whether the counter class is necessary. It seems that it doesn't have the function of encapsulating the integer class at all. Why not use int or integer? In fact, since all collections can hold only object handles, integers cannot be used at all. After learning about collections, the concept of encapsulated classes may be easier for you to understand, because you can't put any basic data types into collections. However, the only thing we can do with the Java wrapper is initialize it to a specific value and then read that value. That is, once the wrapper object has been created, there is no way to change a value. This makes the integer wrapper meaningless to solve our problem, so we have to create a new class to meet our requirements.

3.1 creating "key" classes

In the previous example, We use a standard library class (integer) as a key of hashtable. As a key, it works well because it already has all the conditions for correct operation. However, when using hash table, once we create our own class as a key, we will encounter a very common problem. For example, suppose that a weather forecast system will use groundhog The (groundhog) object is matched to prediction. This looks very intuitive: we create two classes, and then use groundhog as a key and prediction as a value. As follows:

Each groundhog has an identification number, so you can find a prediction in the hash table and just instruct it to "tell me the prediction related to groundhog number 3". The prediction class contains a Boolean value, using math Random () initializes, and a toString () interprets the results for us. In main (), populate a hash table with groundhog and their associated prediction. The hash tables are printed out so that we can see that they have indeed been populated. Then, a groundhog with identification number 3 is used to find the forecast corresponding to the groundhog #3.

It seems very simple, but it is not feasible in practice. The problem is that groundhog inherits from the common object root class (if the base class is not specified at the beginning, all classes eventually inherit from object). In fact, the hashcode () method of object is used to generate the hash code of each object, and only the address of its object is used by default. Therefore, the first instance of Groundhog (3) does not generate a hash code equal to the second instance of Groundhog (3), but we use the second instance for retrieval.

You may think that all you have to do at this time is to correctly override hashcode (). But this is still not possible unless you do another thing: override equals() which is also part of the object. This method is used when the hash table tries to determine whether our key is equal to a key in the table. Similarly, the default object Equals () simply compares object addresses, so one groundhog (3) is not equal to another.

Therefore, in order to use your class as a key in the hash table, you must override hashcode () and equals () at the same time, as shown below:

Note that this code uses the prediction from the previous example, so spring detector Java must be compiled first, or it will be trying to compile spring detector 2 Java get a compile time error.

Groundhog2. Hashcode() returns the groundhog number as an identifier (in this example, the programmer needs to ensure that no two groundhogs coexist with the same ID number). In order to return a unique identifier, the hashcode() equals() method does not need to be able to strictly judge whether the two objects are equal. The equals () method performs two checks: check whether the object is null; If it is not null, continue to check whether it is an instance of groundhog2 (using the instanceof keyword). It should be a groundhog2 even in order to continue to execute equals(). As you can see, this comparison is based on the actual ghnumber. This time, once we run the program, we will see that it finally produces the correct output (many Java library classes cover the hashcode () and equals () methods to adapt to the content provided by ourselves).

3.2 attribute: a type of hashtable

In the first example, we use a hashtable type called properties. In that example, the following program lines:

A static method named getproperties () is called to obtain a special properties object to describe some characteristics of the system. List () is a method of properties that can send content to any streaming output we choose. There is also a save () method that can be used to write the attribute list to a file for later reading with the load () method.

Although the properties class inherits from hashtable, it also contains a hash table to hold a list of "default" properties. Therefore, if an attribute is not found in the main column, the default attribute will be automatically searched.

The properties class can also be used in our program (classscanner.java in Chapter 17 is an example). You can often find more and more detailed descriptions in the user documentation of the Java library.

4. On enumerator

We can now begin to demonstrate the true power of enumeration: separating operations that cross a sequence from the infrastructure of that sequence. In the following example, the printdata class uses an enumeration to move through a sequence and calls the toString () method for each object. At this point, two different types of collections are created: a vector and a hashtable. And fill them with mouse and hamster objects respectively (these classes have been defined earlier in this chapter; note that hamstermaze.java and worksanywhere.java must be compiled first, otherwise the following programs cannot be compiled). Because enumeration hides the structure of the underlying collection, printdata does not know or care about the type of collection from which enumeration comes:

Note printdata Print () takes advantage of the fact that the objects in these collections belong to the object class, so it calls toString (). However, when solving your own practical problems, you often have to ensure that your enumeration passes through a specific type of collection. For example, you might want all the elements in the collection to be a shape with a draw () method. If this happens, you must start from enumeration The object returned by nexterelement() is backtracked to generate a shape.

5. New set

The new collection library takes into account the problem of "containing your own objects" and divides it into two clear concepts:

(1) Collection: a group of individual elements, usually with certain rules applied. Here, a list must contain elements in a specific order, and a set cannot contain any duplicate elements. On the contrary, the concept of bag is not implemented in the new collection library, because list already provides similar functions.

(2) Map: a series of "key value" pairs (which has been fully reflected in the hash table). On the surface, this seems to be a "set" of "key value" pairs But if you try to implement it that way, you will find that the implementation process is quite clumsy. This further proves that it should be separated into separate concepts. On the other hand, you can easily view a part of the map. Just create a collection and use it to represent that part. In this way, the map can return a set of its own keys, a list containing its own values, or a list containing its own key value pairs. Similar to arrays, map can be easily extended to multiple "dimensions" without involving any new concepts. Simply include other maps in one map (the latter can contain more maps, and so on).

After reading through this chapter, I believe you will really understand that it actually has only three collection components: map, list and set. Moreover, each component actually has only two or three implementation methods (note ⑥), and there is usually only one particularly good way. As long as you see this, the collection will no longer be daunting.

6. Using collections

Boolean add (object) * ensure that the set contains arguments. If it does not add an argument, it returns false

Boolean addall (Collection) * adds all elements in the argument. Returns true if no element is added

Void clear() * deletes all elements in the collection

Boolean contains (object) returns true if the collection contains arguments

Boolean containsall (Collection) returns true if the collection contains all the elements in the argument

Boolean isempty() returns "true" if there are no elements in the set. Iterator() returns an iterator to traverse the elements of the set

Boolean remove (object) * if the argument is in the collection, delete an instance of that element. Returns true if a deletion has been made

Boolean removeAll (Collection) * deletes all elements in the argument. Returns true if any deletions have been made

Boolean retain all (Collection) * only the elements contained in an argument (a theoretical "intersection"). If any changes have been made, it returns "true". Int size() returns the number of elements in the collection

Object [] toarray() returns an array containing all elements in the collection

7. Using lists

List (Interface) order is the most important feature of list; it can ensure that the elements are arranged in the specified order. List adds a lot of methods to the collection so that we can insert and delete elements in the middle of the list (only recommended for LinkedList). List will also generate a listiterator (list iterator), which can traverse in two directions in a list, and insert and delete elements in the middle of the list at the same time (similarly, this is only recommended for LinkedList)

ArrayList * a list derived from an array. Used as a general-purpose object container to replace the original vector. Allows us to access elements quickly, but it's a little slower to insert and delete elements from the middle of the list. Generally, you should only use listiterator to traverse an ArrayList forward and backward, and do not use it to delete and insert elements; It is much less efficient than LinkedList

LinkedList provides optimized sequential access performance, and can efficiently insert and delete in the middle of the list. However, in random access, the speed is quite slow. At this time, you should use ArrayList instead. Addfirst(), addlast(), getfirst(), getlast(), removefirst() and removelast() (not defined in any interface or basic class) are also provided to use as a specification, queue and a two-way queue

8. Using sets

Set (Interface) every element added to a set must be unique; otherwise, set will not add duplicate elements. Objects added to a set must define equals() to establish object uniqueness. Set has exactly the same interface as collection. A set cannot guarantee that it can maintain its elements in any particular order

HashSet * is used for all sets except very small ones. Object must also define hashcode()

Arrayset is a set derived from an array. Design for very small sets, especially those that need to be created and deleted frequently. For small sets, the cost of creating and repeating an arrayset is much lower than that of a HashSet. However, with the increase of set, its performance will be greatly reduced. The hashcode () TreeSet does not need to be a sequential set derived from a "red black tree". In this way, we can refer to a sequential set from a set

9. Using maps

Map (Interface) maintains the "key value" correspondence (pair) in order to find the corresponding value through a key

HashMap * is based on a hash table implementation (instead of hashtable). This form has the most stable performance for the insertion and retrieval of key value pairs. This performance can be adjusted through the builder to set the "capability" and "load factor" of hash tables

Arraymap is a map derived from an ArrayList. It provides precise control over the repeated sequence. For very small map designs, especially those that need to be created and deleted frequently. For very small maps, the cost of creating and iterating is much lower than that of HashMap. However, after the map becomes larger, the performance will be greatly reduced accordingly

Treemap is implemented on the basis of a "red black" tree. When viewing key or "key value" pairs, they will be arranged in a fixed order (depending on comparable or comparator, which will be discussed later). The biggest advantage of treemap is that we get ordered results. Treemap is the only map with submap() method, which can return part of the tree

summary

The above is the whole content of this article on the accommodation of Java programming thought objects and the detailed explanation of examples. I hope it can help you and give you more support for this site!

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>