Return to index

Java Basics 7
Strings, Numbers and Arrays

 

Topics covered include :

  • Characters and Strings
  • Numbers
  • Arrays

 

Characters and Strings

Character data - either a single character or a series of characters - can be stored and manipulated by one of three classes in package java.lang: Character, String, and StringBuffer.

  • Character - A class whose instances can hold a single character value. This class also defines handy methods that can manipulate or inspect single-character data.
  • String - A class for working with immutable (unchanging) data composed of multiple characters.
  • StringBuffer - A class for storing and manipulating mutable data composed of multiple characters.

The String class is more efficient when the data it holds is not changed and the StringBuffer class is more efficient for dynamically changed data (changed at run-time), although if the amount of processing is small, you may find it easier to use the String class.

 

Creating Strings and StringBuffers

A String is often created from a 'string literal' - a series of characters enclosed in double quotes. For example, when it encounters the following string literal, the Java platform creates a String object whose value is Gobbledygook.

"Gobbledygook" 

The StringsDemo program uses this technique to create the String object referred to by the variable named palindrome:

String palindrome = "Dot saw I was Tod"; 

You can also create String objects as you would any other Java object: using the new keyword and a constructor. The String class provides several constructors that allow you to provide the initial value of the String object, using different sources, such as an array of characters, an array of bytes, or a StringBuffer.

Here's an example of creating a string from a character array:

char[] helloArray = { 'h', 'e', 'l', 'l', 'o' };
String helloString = new String(helloArray);
System.out.println(helloString); 

The last line of this code snippet displays: hello.

You must always use the new operator to create a StringBuffer object. The StringsDemo program creates the StringBuffer object referred to as dest, using the constructor that sets the buffer's capacity:

String palindrome = "Dot saw I was Tod";
int len = palindrome.length();
StringBuffer dest = new StringBuffer(len); 

This code creates a StringBuffer object with an initial capacity equal to the length of the String object referred to by the name palindrome. This ensures an efficient single memory allocation for dest because it's just big enough to contain the characters that will be copied to it. By initializing a string buffer's capacity to a reasonable first guess, you minimize the number of times memory must be allocated for it. This makes your code more efficient because memory allocation is a relatively expensive operation.

 

Accessor Methods

Getting the length of a String or a String Buffer

Methods used to obtain information about an object are known as accessor methods. One accessor method that you can use with both strings and string buffers is the length() method, which returns the number of characters contained in the string or the string buffer. After the following two lines of code have been executed, len equals 17:

String palindrome = "Dot saw I was Tod";
int len = palindrome.length(); 

In addition to length(), the StringBuffer class has a method called capacity(), which returns the amount of space allocated for the string buffer rather than the amount of space used. For example, the capacity of the string buffer referred to by dest in the StringsDemo program never changes, although its length increases by 1 for each iteration of the loop. The following figure shows the capacity and the length of dest after nine characters have been appended to it.

A string buffer's length is the number of characters it contains; a string buffer's capacity is the number of character spaces that have been allocated. The String class doesn't have a capacity() method, because a string cannot change.

 

Getting characters by index from a String or a String Buffer

You can get the character at a particular index within a string or a string buffer by using the charAt() method. The index of the first character is 0; the index of the last is length()-1. For example, the following code gets the character at index 9 in a string:

String anotherPalindrome = "Niagara. O roar again!"; 
char aChar = anotherPalindrome.charAt(9); 

Indices begin at 0, so the character at index 9 is 'O', as illustrated in the following figure:

Use the charAt() method to get a character at a particular index. The figure also shows that to compute the index of the last character of a string, you have to subtract 1 from the value returned by the length() method.

If you want to get more than one character from a string or a string buffer, you can use the substring() method. The substring method has two versions, as shown in the following table:

Method Description
String substring(int)
Returns a new string that is a substring of this string or string buffer.The integer argument specifies the index of the first character. The substring extends to the end of the original string.
String substring(int, int) The first integer argument specifies the index of the first character. The second integer argument is the index of the last character -1. The length of the substring is therefore the first int minus the second int.


The following code gets from the Niagara palindrome the substring that extends from index 11 to index 15, which is the word "roar":

String anotherPalindrome = "Niagara. O roar again!"; 
String roar = anotherPalindrome.substring(11, 15);  

Use the substring() method to get part of a string or string buffer. Remember that indices begin at 0.

Converting Objects to Strings

All classes inherit method toString() from the Object class. Most classes override this method to provide an implementation that is meaningful to that class. For example, the Rectangle class overrides method toString() to return a String that describes an instance's origin, width and height.

 

The valueOf() Method

As a convenience, the String class provides the static method valueOf(). You can use method valueOf() to convert variables of different types to Strings. For example, to print the value of pi:

System.out.println(String.valueOf(Math.PI));

 

Converting Strings to Numbers

The String class itself does not provide any methods for converting a String object to a floating point, integer, or other numerical type. However, four of the 'type wrapper' classes (Integer, Double, Float, and Long) provide a static method named valueOf(String s) that converts a String object to an object of that type. Here's a small, contrived example that uses the Float class's valueOf() method:

try {
     String piStr = "3.14159";
     Float pi = Float.valueOf(piStr);
} catch (NumberFormatException ex) {}

 

String Literals

In Java, you specify 'literal strings' between double quotes:

"Hello World!" 

You can use literal strings anywhere you would use a String object. For example, System.out.println() accepts a String object argument, so you could also use a literal string there.

System.out.println("Might I add that you look lovely today."); 

You can also use String methods directly from a literal string.

int len = "Goodbye Cruel World".length(); 

You can do this because the compiler automatically creates a new String object for every literal string it encounters.

You can use a literal string to initialize a String object.

String s = "Hola Mundo"; 

The above construct is equivalent to, but more efficient than, this one, which actually creates two String objects:

String s = new String("Hola Mundo"); 

The compiler creates the first string when it encounters the literal string "Hola Mundo!", and the second one when it encounters new String.

 

Concatenation and the + Operator

In the Java programming language, you can use + to concatenate (join) Strings together:

String cat = "cat";
System.out.println("con" + cat + "enation"); 

This is a little deceptive because, as you know, String objects can't be changed. However, behind the scenes the compiler uses StringBuffer objects to implement concatenation. The above example compiles to:

String cat = "cat";
System.out.println(new StringBuffer().append("con")
                       .append(cat).append("enation").toString()); 

You can also use the + operator to append values to a String that are not themselves Strings:

System.out.println("Java's Number " + 1); 

The compiler converts the non-String value (the integer 1 in the example) to a String object before performing the concatenation operation.

 

Useful StringBuffer methods include :

  • String toString()
  • StringBuffer append(xxx) - various versions
  • StringBuffer insert(int offset, xxx) - various versions
  • void setCharAt(int index, char c)
  • StringBuffer deleteCharAt(int offset)
  • StringBuffer delete(int startIndex, int endIndex)
  • void setLength(int length)
  • String substring(int startIndex, int endIndex)


Useful String methods include :

  • int indexOf(String / char)
  • int lastIndexOf(String / char)
  • String toLowerCase()
  • String toUpperCase()
  • String replace(char oldChar, char newChar)
  • boolean equals(String)
  • int compareTo(String) - useful for alphabetical sorting
  • String substring(int startIndex, int endIndex)
  • boolean startsWith(String)
  • boolean endsWith(String)

 

Characters

An object of class Character contains a single character value. You can use a Character object instead of a primitive char variable whenever an object is required. For example, when passing a character value into a method that changes the value or when placing a character value into a data structure, such as a Vector, that requires objects.

The following example program, CharacterDemo, creates a few character objects and displays some information about them.

public class CharacterDemo {
      public static void main(String args[]) {
            Character a = new Character('a');
            Character a2 = new Character('a');
            Character b = new Character('b');
            int difference = a.compareTo(b);
            if (difference == 0) {
                  System.out.println("a is equal to b.");
            } else if (difference < 0) {
                  System.out.println("a is less than b.");
            } else if (difference > 0) {
                  System.out.println("a is greater than b.");
            }
            System.out.println("a is "
                 + ((a.equals(a2)) ? "equal" : "not equal")
                 + " to a2.");
            System.out.println("The character " + a.toString() + " is "
                 + (Character.isUpperCase(a.charValue()) ? "upper" : "lower")
                 + "case.");
    }
} 

The following is the output from this program:

a is less than b.
a is equal to a2.
The character a is lowercase. 

The CharacterDemo program calls the following constructor:

Character(char)

This is the Character class's only constructor, which creates a Character object containing the value provided by the argument. Once a Character object has been created, the value it contains cannot be changed.

int compareTo(Character)

The class Character has a method that compares the values held by two character objects: the object on which the method is called (a in the example) and the argument to the method (b in the example). This method returns an integer indicating whether the value in the current object is greater than, equal to, or less than the value held by the argument. A character is greater than another character if its numeric value is greater.

boolean equals(Object)

A method that compares the value held by the current object with the value held by another. This method returns true if the values held by both objects are equal.

String toString()

A method that converts the object to a string. The resulting String is one character in length and contains the value held by the Character object.

char charValue()

A method that returns the value held by the Character object as a primitive char value.

boolean Character.isUpperCase(char)

A static method that determines whether a primitive char value is uppercase. This is one of many Character class methods that inspect or manipulate character data.

Note to C and C++ Programmers:  Java String objects are first-class objects, unlike C and C++ strings, which are simply null-terminated arrays of 8-bit characters.

 

Numbers

To work with numeric data, you use the number classes. The Number class is the superclass for all number classes in the Java platform (java.lang.Number). Its subclasses include Float, Integer, and so on.

There are some other classes that you might find useful when working with numbers.

If you need to display a number in a particular format, you can use the NumberFormat and DecimalFormat classes in package java.text to format them.

The Math class in package java.lang contains methods that perform mathematical functions beyond those provided by the Java language itself. The Math class contains methods for performing basic numeric operations such as exponential, logarithm, square root and trigonometric functions.

The Random class in package java.util provides methods for the generation of random numbers.

 

 

Arrays

An array is an important data structure in any programming language. An array is a fixed-length structure that stores multiple values of the same type.

Arrays are supported directly by the Java programming language; there is no array class (however, there is class java.lang.reflect.Array that provides static methods to dynamically create and access Java arrays).

Arrays are implicit extensions of the Object class, so you can assign an array to a variable whose type is declared as Object.

An array is a structure that holds multiple values of the same type. The length of an array is established when the array is created (at runtime). After creation, an array is a fixed-length structure.

An 'array element' is one of the values within an array and is accessed by its position (index) within the array.

If you want to store data of different types in a single structure, or if you need a structure whose size can change dynamically, use a Collection implementation, such as class Vector, instead of an array.

Here's a simple program, called ArrayDemo, that creates an array, puts some values in it, and then displays those values.

public class ArrayDemo {
      public static void main(String[] args) {
            int[] anArray;    // declare an array of integers
            anArray = new int[10];    // create an array of integers
            // assign a value to each array element and then print it out
            for (int i = 0; i < anArray.length; i++) {
                  anArray[i] = i;
                  System.out.print(anArray[i] + " ");
            }
            System.out.println();
      }
} 

This brings us to a potential stumbling block, often encountered by new programmers, when using arrays that contain objects. Consider this line of code:

String[] anArray = new String[5]; 

After this line of code is executed, the array called anArray exists and has enough room to hold 5 String objects. However, the array doesn't contain any strings yet. It is empty. The program must explicitly create String objects and put them in the array. This might seem obvious, but many beginners assume that the previous line of code creates the array and creates 5 empty strings in it.

 

Declaring a Variable to Refer to an Array

This line of code from the sample program declares an array variable:

int[] anArray;    // declare an array of integers 

Like declarations for variables of other types, an array declaration has two components: the array's type and the array's name. An array's type is written type[], where 'type' is the data type of the elements contained within the array, and [] indicates that this is an array. Remember that all of the elements within an array must be of the same type. The example program uses int[], so the array called anArray will be used to hold integer data.

As with declarations for variables of other types, the declaration for an array variable does not allocate any memory to contain the array elements. You must assign a value to anArray before the name refers to an array.

 

Creating an Array

You create an array explicitly using Java's new operator. The next statement in the example program allocates an array with enough memory for ten integer elements and assigns the array to the variable named anArray declared earlier.

anArray = new int[10];    // create an array of integers 

In general, when creating an array, you use the new operator, plus the data type of the array elements, plus the number of elements desired enclosed within square brackets ('[' and ']').

new elementType[arraySize] 

If the new statement were omitted from the example program, the compiler would print an error like the following one and compilation would fail.

ArrayDemo.java:4: Variable anArray may not have been initialized.

 

Accessing an Array Element

Now that some memory has been allocated for the array, the program can assign values to the array elements:

for (int i = 0; i < anArray.length; i++) {
      anArray[i] = i;
      System.out.print(anArray[i] + " ");
} 

This part of the code shows that to reference an array element, either to assign a value to it, or to access the value, you append square brackets to the array name. The value between the square brackets indicates (either with a variable of primitive type int or some other expression that evaluates to an int) the index of the element to access.

Note that in Java, array indices begin at 0 and end at the array length minus 1.

 

Getting the Size of an Array

To get the size of an array, you write

arrayname.length 

Be careful: programmers new to the Java programming language are tempted to use arrayname.length(). This doesn't work because length is not a method - length is a property provided by the Java platform for all arrays.

The for loop in our example program iterates over each element of anArray, assigning values to its elements. The for loop uses anArray.length to determine when to terminate the loop.

 

Array Initializers

The Java programming language provides a shortcut syntax for creating and initializing an array. Here are two examples of the use of this syntax:

boolean[] answers = { true, false, true, true, false };
int[] scores = { 34, 87, 91, 55, 26 }; 

The length of the array is determined by the number of values provided between { and }.

 

Arrays of Arrays

It is possible to have an array of arrays. For example:

int[][] aMatrix = new int[3][3]; 

You must specify the length of the primary array when you create the array. However, you can leave the length of the sub-array unspecified until you create it.

 

Copying Arrays

Finally, note that you can use class System's static method

arraycopy(Object src, int src_position, Object dst, int dst_position, int length)

to efficiently copy data from one array into another.

This method copies an array from the specified source array, beginning at the specified position, to the specified position of the destination array. A subsequence of array components are copied from the source array referenced by src to the destination array referenced by dst. The number of components copied is equal to the length argument. The components at positions srcOffset through srcOffset+length-1 in the source array are copied into positions dstOffset through dstOffset+length-1, respectively, of the destination array.

If the src and dst arguments refer to the same array object, then the copying is performed as if the components at positions srcOffset through srcOffset+length-1 were first copied to a temporary array with length components and then the contents of the temporary array were copied into positions dstOffset through dstOffset+length-1 of the destination array.

 

and finally ...

The Java platform groups its classes into functional packages. Most of the classes discussed in this chapter are members of the java.lang package. All the classes in the java.lang package are available to your programs automatically - you do not need an import statement for package java.lang.

 

Download and run ...

You can download the source code for the example programs as a TJI project from the 'Resources' page of our website.

 

NOTE : This document was based on parts of the excellent book 'The Java Tutorial' by Mary Campione, Kathy Walrath and Alison Huml; also on-line at Sun's Java site.


Return to index