Useful methods, the Standard Library, and streams

A library is a collection of related modules that provides reusable functionality to simplify development. The Java Standard Library is a collection of pre-written classes and APIs that provide essential functionality for Java development, such as data structures, networking, file I/O, and utilities and is bundled with the Java Development Kit (JDK). In this lesson, we will use the built-in classes from this library. We import these classes using the import statement, e.g., import java.util.Random;.

The Random class

The Random class is used to generate random numbers. The numbers generated using this class are pseudorandom, which means they are drawn according to a certain pattern. The initial value used by the generator is called a seed. If we know the value of the seed, we can predict the rest of the numbers produced by the generator because, for a given seed, the same numbers will always be generated (in the same order). The seed can be set with the randomObject.seed(value) command.


import java.util.Random;

public class Main {
    public static void main(String[] args) {
        Random rand1 = new Random();
        long seed = (long) 3.142;
        Random rand2 = new Random(seed);
        long newseed = (long) 2.7182;
        rand2.setSeed(newseed); // changing the seed

        int i = rand1.nextInt(); // drawing integers without a range
        double d = rand1.nextDouble(); // drawing double numbers without a range

        System.out.println("Random integer: " + i);
        System.out.println("Random double: " + d);

        // Drawing integers (we determine the range in the arguments - start, stop)
        i = rand1.nextInt(5, 25); // (first value - inclusive, last value - exclusive)
        System.out.println("Random integer in range [5, 25): " + i);

        i = rand1.nextInt(25); // 0 is the default first value
        System.out.println("Random integer in range [0, 25): " + i);

    }
}
                                    

Streams

Streams provide a way to process data sequences, including collections and arrays, in a functional style. The Stream API allows us to perform operations such as filtering, mapping, and reducing data sets concisely. The Random class offers methods like doubles(), ints(), and longs() that return streams of random values of the specified type (they can be customized with parameters to define range). This enables the generation of random numbers within specific bounds. By using streams, we can efficiently handle large volumes of data and perform complex operations. Additionally, streams support lazy evaluation, meaning random numbers are generated on the fly as they are consumed, leading to performance optimizations when not all values are needed simultaneously (we do not need to store the whole sequence).

Here’s how we can create a stream of random doubles:


Random rand1 = new Random();
DoubleStream stream = rand1.doubles(0, 10).limit(10); // 10 double numbers from the range 0-10
stream.forEach(System.out::println); // displaying all of the stream values
                                    

The Math class

The Math class provides more complex mathematical operations.


import java.lang.Math;

public class Main {
    public static void main(String[] args) {
        int x = 16;
        double y = 3.14;

        System.out.println(Math.ceil(y)); // rounding up a number
        System.out.println(Math.floor(y)); // rounding down a number

        System.out.println(Math.sqrt(x)); // calculating the square root of a number
        System.out.println(Math.pow(x, 2)); // raising a number to a given power
        System.out.println(Math.log(y)); // calculating the natural logarithm of y (base e)

        System.out.println(Math.PI); // displaying the PI number
        System.out.println(Math.E); // displaying the E number
    }
}
                                    

The Calendar and Date classes

These classes are used to handle time. Creating and instance of the Date class will assign the current date and time to a variable: final Date date = new Date();.


import java.util.Calendar;
import java.util.Date;

public class Main {
    public static void main(String[] args) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, 2023);
        calendar.set(Calendar.MONTH, 0); // January
        calendar.set(Calendar.DATE, 8);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);

        Date date = calendar.getTime(); // converting the calendar instance to a Date object
        System.out.println(date);
    }
}
                                    

The Arrays class

The Arrays class allows us to, e.g., sort arrays.


import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[] numbers = new int[] {5, 2, 8, 1, 3};

        Arrays.sort(numbers); // sorting an array

        for (int num : numbers)
            System.out.println(num);
    }
}
                                    

The System class

The System class is used to handle system operations.


import java.lang.System;

public class Main {
    public static void main(String[] args) {
        long currentTime = System.currentTimeMillis(); // getting the current time in milliseconds
        System.out.println("Current time in milliseconds: " + currentTime);

        String userHome = System.getenv("HOME"); // getting the environment variables
        System.out.println("User's home directory: " + userHome);

        System.exit(0); // ending the program
    }
}
                                    

The String class

The String class is used to manipulate strings.


import java.lang.String;

public class Main {
    public static void main(String[] args) {
        String str = "Hello World!";
        
        // Checking the number of characters in a string (its length)
        System.out.println("String length: " + str.length());

        // Returning a part of a string (a substring)
        System.out.println("Substring: " + str.substring(0, 5)); // "Hello" (starting index - inclusive, stopping index - exclusive)

        // Lowercase to uppercase
        System.out.println("Uppercase: " + str.toUpperCase());
        
        // Uppercase to lowercase
        System.out.println("Lowercase: " + str.toLowerCase());
        
        // Comparing strings
        String str2 = "Hello World!";
        System.out.println("Strings are equal: " + str.equals(str2));

        // Breaking a string into an array by dividing it every time a given delimiter is encountered
        String[] words = str.split(" "); // the space is the delimiter (we can choose a different one)
        for (String word: words)
            System.out.println(word);
        // We can limit the number of splits by passing a second argument, e.g., split(" ", 2). This ensures that only the first space splits the string while the rest remains intact.

        // Joining the elements of an array into a single string by inserting a delimiter between each element
        String joined = String.join(" ", words);
        System.out.println(joined);

        // Checking if a string contains a specified substring
        boolean result = str.contains("World");
        System.out.println(result);

        // Finding the position of the first occurrence of a substring in a string (the index of the substring's first letter). If there are more than one - the index of the first one encountered.
        int pos = str.indexOf("World");
        if (pos != -1) // checking if the substring was found
            System.out.println("Found at position: " + pos);
        else
            System.out.println("Not found");
    }
}
                                    

The StringBuilder class

The StringBuilder class is used for creating and modifying mutable strings. Unlike String, which creates a new object on every modification, it allows for more efficient string manipulation.


import java.lang.StringBuilder;

public class Main {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder("Hello");
        
        // Appending to the string
        sb.append(" World!");
        System.out.println(sb); // "Hello World!"
        
        // Inserting into the string
        sb.insert(5, ",");
        System.out.println(sb); // "Hello, World!"
        
        // Reversing the string
        sb.reverse();
        System.out.println(sb); // "!dlrow ,olleH"
    }
}
                                    

Converting between strings and numbers


String str = "15";

// String to integer
int i = Integer.parseInt(str);
System.out.println(i);

// String to float
float f = Float.parseFloat(str);
System.out.println(f);

// Integer to string 
Integer i2 = 15; // the type has to be an object (even our class if it overrides the toString() method)
String str1 = i2.toString(); // if i2 is null, it would throw a NullPointerException (an error)
System.out.println(str1);

// Integer to string
int i3 = 15; // the type has to be primitive
String str2 = String.valueOf(i3); // a primitive type can't be null
System.out.println(str2);