String, StringBuffer and Math Classes

Create and Manipulate Strings

Once a string object is created it can never be changed, string objects are immutable objects. String objects are created using the new keyword, or assigning text to a String variable the String class has many constructors.

String creation examples
// Using the new keyword means a String object will be created
// there are many String constructors that can be used 
String s = new String();
s = "Using the new keyword";

String s = new String("Using a one liner");

// The below creates the string in the string constant pool (see below for more information)
// this actually makes Java more efficient
String s = "Using the shorthand version"; 

// There are constructors for chars and bytes
char chars[] = { 'a', 'b', 'c' };
String s = new String(chars);

byte ascii[] = { 65, 66, 67, 68, 69 };
String s = new String(ascii);

To make Java more efficient the JVM sets aside a special area of memory called the "String constant pool", When the compiler encounters a String literal, it checks the pool to see if an identical String already exists. If a match is found, the reference to the new String is directed to the existing String and no new String object is created (The existing String simply has an additional reference). To stop stop any problems in the String pool, the String class is marked final nobody can override the behaviors of any of the String methods, so you can be assured that the String objects you are counting on to be immutable will in fact be immutable, this is called interning

As I stated above String objects can never be changed, what happens when you appear to change a string object is that a new string object is created and the string variable points to the new string object, the old string object is deposed of by the garbage collector.

Strings are immutable

String s = new String("Using a one liner");

s = s.concat("you are not supposed to be able to change this");

Note: what happens is the following

  1. A new string object is created using the original string with the concatenation
  2. the string variable s now points to the new string object
  3. the old string object is removed by the garbage collector as long as nothing else is attached to it.

There are a number of categories for String methods

Category Methods
Comparison equals
equalsIgnoreCase
contentEquals
compareTo
isEmpty
isBlank
Text Searches contains
equalsIgnoreCase
endsWith
indexOf
lastIndexOf
matches
startsWith
Text Manipulation concat
join
replace
replaceAll
replaceFirst
split
substring
subsequence
Text Transformation chars
codePoints
format
lines
repeat
strip
stripLeading
stripTrailing
toCharArray
toLowerCase
toUpperCase
trim
valueOf

Here are some of the more commonly used String methods, check the documentation for a full list

charAt

String x = "Hello World!";
System.out.println("Character 3 in String x is " + x.charAt(2));

Note: The charAt returns the character at a specific index, remember we start at zero

compareTo

String t = "Hello";
String t1 = "World";
String t2 = t;

System.out.println( t + " compareTo " + t2 + " results in " + t.compareTo(t2));   // results in 0 (match)
System.out.println( t + " compareTo " + t1 + " results in " + t.compareTo(t1));   // results in -15

Note: a reult of zero means that they are equal, a negative values means it is less than the string passed, and a positive values means it is more than the value passed

concat
String x = "Taxi";
System.out.println( x.concat(" cab");
System.out.println("Original String x has now been changed : " + x);

Note: concat method does not update x as there was no assignment 

Note: you can also use the + operator (plus) to concat a string as well.
equals

String x = "hello";

if ( x.equalsIgnoreCase("hello")
   System.out.prinln("String x is equal to Hello, hello, etc");

Note: see equals for more information on this method

equalsIgnoreCase

String x = "hello";

if ( x.equalsIgnoreCase("Hello")
   System.out.prinln("String x is equal to Hello, hello, etc");

Note: the equalsIgnoreCase returns true if the value is the same as the argument passed, otherwise false

getChars

# getChars(int srcBegin, int srcEnd, char[] dest, int destBegin)

String h = "Hello World";
char[] ca = new char[5];

h.getChars(0, 5, ca, 0);
System.out.println(ca);

indexOf and lastIndexOf String s1 = "abcdefghijklmabcdefghijklm";

System.out.println("String is: " + s1 + "\n");

System.out.println("first c is found @ position: " + s1.indexOf('c') );
System.out.println("fgh is found @ position: " + s1.indexOf("fgh") );
System.out.println("fgh is found @ position (skip first 7 characters): " + s1.indexOf("fgh", 7) );

System.out.println("unknown $ is not found: " + s1.indexOf('$') );

System.out.println("last c is found @ position: " + s1.lastIndexOf('c') );
intern

String t1 = "abcdefghiklmnopqrstuvwxyz";
String t2;

t2 = t1.intern();   // see note below

if ( t1 == t2)
   System.out.println("t1 and t2 are the same object");

if ( t1.equals(t2) )
   System.out.println("t1 and t2 have the same contents");

Note: when using intern you are looking in the string constant pool a special area in the heap memory, you can force a string to be added to the pool by calling the intern method on the string

join
// Will join the strings using spaces inbetween, the first field is the join character/s
String result = String.join(" ", "Will", "Moore", "Graham");                 
System.out.println(result);
length

String x = "this is a very long string that hopefully will have a total of 76 characters";

System.out.println("String x has " + x.length() + " Character");

Note: return the length of a String (includes whitespace)

regionMatches # regionMatches(start offset, string, start offset of the subregion, number of characters to compare)
# regionMatches(ignore case, start offset, string, start offset of the subregion, number of characters to compare)

String t = "Hello";
String match = "hello";

if ( t.regionMatches(0, match, 0, 5) )
   System.out.println("A perfect match");
else
   System.out.println("Not a perfect match");

if ( t.regionMatches(true, 0, match, 0, 5) )
   System.out.println("A perfect match");
else
   System.out.println("Not a perfect match");
}
replace

String x = "XXaXX";

System.out.println("String before: " + x);
System.out.println("String replaced: " + x.replace('X','x'));

substring
String x = "1234567890";
System.out.println("Part of String x: " + x.substring(5));    // start from position 5 return rest of string
System.out.println("Part of String x: " + x.substring(5,8));  // start from position 5 return upto character 8 

// Insert string into middle of a sentence  
String insert = "Tutorial";
String sentence = "Java 11";

int index = sentence.indexOf(" ");
System.out.println("Index: " + 4);

sentence = sentence.substring(0, index + 1) + insert + sentence.substring(index);
System.out.println(sentence);  

Note: used to return part of a string 
toLowerCase toUpperCase

String lower = "all lower case";
String upper = "ALL UPPER CASE";

System.out.println("String lower is now upper case: " + lower.toUpperCase());
System.out.println("String upper is now lower case: " + upper.toLowerCase());

toString

String x = "Hello World!";

System.out.println("toString method returns: " + x.toString());

Note: all objects in Java have a toString method, normally returns a meaningful way to describe the object

trim

String x = "     x     ";

System.out.println("Blank spaces removed from x: " + x.trim());

Note: trim removes any leading or trailing blank spaces

valueOf int i = 20;
boolean b = true;
double d = 100.20;

System.out.println("integer string is: " + String.valueOf(i) );
System.out.println("boolean string is: " + String.valueOf(b) );
System.out.println("double string is: " + String.valueOf(d) );

String Formatting

To format strings you can use either printf or format (interchangeable), there are a number of options that you can use to help with the formatting, an example of these are below see full documentation for a complete list.

String formatting examples
public class string_formatting_1 {

    public static void main(String[] args) {
        String s1 = "Hello";
        String s2 = "World";
        String s3 = "The day after tomorrow";
        String s4 = "Open 24 hours";
        String name = "Paul Valle";
        Double decimalNum = 45.6784;
        Integer bigNum = 123456789;

        Date date = new Date();

        System.out.println(s1 + " " + s2);

        String strConcat = s1.concat(" " + s2);
        System.out.println(strConcat);

        // Using printf and format (both are interchangeable)

        // %n = newline, you can also use %d, %f %e for numbers
        System.out.printf("I am %d years old %n", 100);
        System.out.printf("%,d (using , separator)", bigNum);

        System.out.format("I am %d years old %n", 100);
        System.out.format("%,d (using , separator)", bigNum);

        // use %s for strings
        System.out.printf("%20s (right justified) %n", name);
        System.out.printf("%-20s (left justified) %n", name);
        System.out.printf("%10.5s (padding.num of chars) %n", decimalNum);
        System.out.printf("%-10.5s (padding.num of chars) %n", decimalNum);

        System.out.format("%20s (right justified) %n", name);
        System.out.format("%-20s (left justified) %n", name);
        System.out.format("%10.5s (padding.num of chars) %n", decimalNum);
        System.out.format("%-10.5s (padding.num of chars) %n", decimalNum);

        // use locale
        Locale italian_locale = Locale.ITALIAN;
        System.out.printf(italian_locale, "The date is %tc %n", date);
        System.out.printf(Locale.US, "The date is %tc %n", date);

        System.out.format(italian_locale, "The date is %tc %n", date);
        System.out.format(Locale.US, "The date is %tc %n", date);
    }
}
Formatting arrays
public class string_formatting_lists_1 {

    public static void main(String[] args) {
        int[] a1 = {1,2,3,4,5};

        for (int i = 0; i < a1.length; i++) {
            System.out.println(a1[i]);
        }

        // don't print the last separator
        for (int i = 0; i < a1.length; i++) {
            System.out.print(a1[i]);
            if (i < a1.length - 1) {
                System.out.print(", ");
            }
        }
        System.out.println();

        // You have to keep track of the index yourself using a for loop
        int index = 0;
        for (int i : a1) {
            System.out.print(i);
            if (index != a1.length - 1) {
                System.out.print(", ");
            }
            index++;
        }
        System.out.println();

        // There are many ways here another way
        StringJoiner sj = new StringJoiner(", ");
        for (int i : a1)
        {
            sj.add(Integer.toString(i));
        }
        System.out.println(sj);

        // Very quick way
        System.out.println(String.join(", ", Arrays.toString(a1)));

        // Using lambda's
        String a2 = Arrays.stream(a1)
                .mapToObj(i -> Integer.toString(i))
                .collect(Collectors.joining(", "));
        System.out.println(a2);
    }
}

Manipulate data using the StringBuffer class and its methods

If you modify a String object many times you end up will lots of abandoned String objects in the String pool, this is where the StringBuffer comes in as it is not immutable, which means they can be modified over and over without leaving any abandoned objects. A common use for StringBuffers is file I/O, especially if we are talking large amounts of data.

StringBuffer

StringBuffer sb1 = new StringBuffer();              // this will have an initial capacity of 16 characters
StringBuffer sb2 = new StringBuffer(10);            // this will have a capacity of 10 characters

StringBuffer sb3 = new StringBuffer("Hello World!");  // the capacity will be string size 12 plus 16 = 32

System.out.println("StringBuffer sb3 is: " + sb3);    // Just use it like a String

Again the StringBuffer class has many methods, here are some of the more common ones

append

StringBuffer sb = new StringBuffer("abcd");

System.out.println("Appends efgh to StringBuffer sb :" + sb.append("efgh");
System.out.println("StringBuffer sb is now: " + sb);

Note: There are 10 overloaded append methods which allow you to add various data type values

capacity

StringBuffer sb1 = new StringBuffer();
StringBuffer sb1 = new StringBuffer(10);
StringBuffer sb1 = new StringBuffer("Hello World");

System.out.prntln("StringBuffer sb1(character count): " + sb1);     // displays 0
System.out.prntln("StringBuffer sb2(character count): " + sb2);     // displays 0
System.out.prntln("StringBuffer sb3(character count): " + sb3);     // displays 11

System.out.prntln("StringBuffer sb1(capacity): " + sb1);     // displays 16
System.out.prntln("StringBuffer sb2(capacity): " + sb2);     // displays 10
System.out.prntln("StringBuffer sb3(capacity): " + sb3);     // displays 27

Note: increasing the size is a performance hit, so if you do change the StringBuffer make sure it has the capacity already so it does not need to grow

charAt, setCharAt, getChars These are the same the String methods above
ensureCapacity

StringBuffer sb1 = new StringBuffer();
sb1.ensureCapacity(75);                 // minimum capacity will be 75 characters

Note: if the character length is greater then the method ensures a capacity that is the greater of the number specified as an argument or twice the original capacity plus 2.

delete

## sb.delete(start position, end position)
StringBuffer sb = new StringBuffer("1234567890");

System.out.println("Inserted text into StringBuffer sb: " + sb.delete(4, 6));  / displays 12347890

insert

## sb.insert(start, data type) there are many diffrent data types i.e boolean, char, String, etc
StringBuffer sb = new StringBuffer("1234567890");

System.out.println("Inserted text into StringBuffer sb: " + sb.insert(4, "----"));

Note: again the offset is zero based

length

StringBuffer sb1 = new StringBuffer();
StringBuffer sb2 = new StringBuffer(10);
StringBuffer sb3 = new StringBuffer("Hello World");

System.out.println("StringBuffer sb1: " + sb1.length());     // displays 0 
System.out.println("StringBuffer sb2: " + sb2.length());     // displays 0
System.out.println("StringBuffer sb3: " + sb3.length());     // displays 11

Note: the length method only returns the character count not the size of the StringBuffer - see capacity

reverse

StringBuffer sb = new StringBuffer("1234567890");

System.out.println("Reversed StringBuffer sb:" + sb.reverse());

setLength

StringBuffer sb1 = new StringBuffer("Hello World");
sb1.setLength(5);
System.out.prntln("sb1: " + sb1);     // displays Hello, it truncated the original

Note: setLength will truncate any characters if the capacity is less than the String contained inside it

toString

StringBuffer sb = new StringBuffer("1234567890");

System.out.println("StringBuffer sb:" + sb.toString());

StringTokenizer Class

When you read a sentence you break it up into words, or tokens, StringTokenizer breaks a string into its component tokens. Tokens are sperated by a delimiter such as white space, coma, colo, etc.

StringTokenizer

import java.util.StringTokenizer;

public class stringTokenizerTest {
   public static void main(String[] args) {

      String s = "This is the string to be tokenized by delimiting whitespaces";
      StringTokenizer tokens = new StringTokenerizer(s);

      System.out.println("There are " + tokens.countTokens() + " tokens" );

      System.out.println("The tokens are: ")
      while( tokens.hasMoreTokens() )
         System.out.println( tokens.nextToken() );
   }
}

StringTokenizer (delimiter)

String s = "This:is:the:string:to:be:tokenized:by:delimiting:whitespaces";
String delimiter = ":";
      
StringTokenizer tokens = new StringTokenerizer(s, delimiter);   // here we change the delimiter

StringTokenizer has other methods that you can use: hasMoreElements, nextElement

Math Class

The Math class is used to perform basic mathematical operations. The Math class defines approximations for the mathematical constants pi and e.

PI public final static double Math.PI
E public final static double Math.E

Because all methods in the Math class are static you do not need to create an instance for them, it is impossible as the constructor for the Math class is marked private. You cannot extend the Math class either as it is marked final.

The Math class has a number of different methods, here are some of the more common ones

abs()

x = Math.abs(99);       // returns 99
x = Math.abs(-99);      // returns the absolute value 99

Note: there are many overloaded methods that can take int, long, float, etc

ceil()

x = Math.ceil(9.0);     // result is 9.0
x = Math.ceil(8.8);     // result is 9.0
x = Math.ceil(8.01);    // still rises to 9.0

Note: there is only one ceil method, ceil(double a)

exp() x = Math.exp(1.0);       // result is 2.71828
x = Math.exp(2.0);       // result is 7.38906
floor()

x = Math.floor(9.0);     // result is 9.0
x = Math.floor(9.4);     // result is 9.0
x = Math.floor(9.99);    // still drops to 9.0

Note: there is only one ceil method, ceil(double a)

max()

x = Math.max(1024, 1023);    // result is 1024

Note: there are many overloaded methods that can take int, long, float, etc

min()

x = Math.min(1024, 1023);    // result is 1023

Note: there are many overloaded methods that can take int, long, float, etc

pow() x = Math.pow(2.0, 7.0);      // result is 128.0 (2*2*2*2*2*2*2)
x = Math.pow(9.0, 0.5);      // result is 3.0   (9.0 * 0.5)
random()

for ( int i = 1; i < 5; i++) {
   System.out.println( (int) (Math.random()*10) + " ");

Note: returns a random double number between 0.0 and 1.0

round() x = Math.round(-10.5);       // result is -10

Note: if equal to or greater that 0.5 then number is rounded up, otherwise rounded down
sin(), cos() and tan() x = Math.sin(Math.toRadians(90.0));   // result is 1.0

x = Math.cos(Math.toRadians(0.0));    // result is 1.0

x = Math.tan(Math.toRadians(45.0));   // result is 1.0
sqrt() x = Math.sqrt(9.0);          // result is 3.0
toDegrees() x = Math.toDegrees(Math.PI * 2.0);    // result 360.0
toRadians() x = Math.toRadians(360.0);   // result is 6.283185