[Java] Various methods to acquire the value stored in List by iterative processing

First stage

In this article, I will introduce some operation methods of iterative processing using the data structure of List regardless of implementation.

The content of the article is at the level of common sense for those who usually program using Java, so the target audience is beginners to intermediates who have just started learning Java. However, it seems that few people are still using the iterative process using the forEach method added in JDK 1.8 at the development site, so I would like you to remember how to use the forEach method at this time. ..

Note that this article deals with simple iterations using the List collection, so we won't touch on the Stream API, which performs intermediate operations such as filter. I would like to introduce the Stream API in another article.

What you can do by reading this article

--Iterative processing using List collection

Operation method of main iterative processing

--Random access using the get (int) method --Sequential access using extended for statement --Sequential access using the forEach (Consumer <T>) method (JDK 1.8 or later)

Random access using the get method

Since the introduction of convenient and efficient functions such as the extended for statement and the forEach method in JDK 1.8, there is almost no need to use the get method for the List collection and iterate with random access. I did. However, this random access is the most basic iterative method using the List collection, regardless of implementation, so be sure to remember it if you are programming in Java.

The basic operation method is as follows.

import java.util.List;
import java.util.ArrayList;

public final class TestGet {

    public static void main(String[] args) {
        final List<String> testList = new ArrayList<>(3);
        testList.add("test1");
        testList.add("test2");
        testList.add("test3");

        for (int i = 0, size = testList.size(); i < size; i++) {
            //Get the i-th element of the variable (random access)
            System.out.println(testList.get(i));
        }
    }
}

In the sample code above, we first implement a test List that can store three elements as ʻArrayList, and then ʻadd the test values.

After that, the basic for statement is used, and the process is repeated for the size of testList prepared earlier. In the above sample code, the variable ʻiis incremented each time it is repeated, so as you can see in the comment, the processing oftestList.get (i)is sequentially performed on the elements oftestList`. It will be randomly accessed.

Therefore, the execution result of the above sample code is output as follows.

test1
test2
test3

important point

--Be sure to clarify the accessible range when performing random access

When using random access using the get method as in the sample code above, be sure to check the size of the List to be accessed. If you specify an index larger than the size of the target List in the get method, ʻIndexOutOfBoundsException` will always occur at runtime and the process will fail.

For example, in the following cases.

import java.util.List;
import java.util.ArrayList;

public final class TestIndexOutOfBoundsException {

    public static void main(String[] args) {
        final List<String> testList = new ArrayList<>();
        testList.add("test1");
        testList.add("test2");
        testList.add("test3");

        //Specify a fourth index that does not exist
        testList.get(3);
    }
}

When I run the sample code above, I get the following exception:

java.lang.IndexOutOfBoundsException: Index 3 out of bounds for length 3
    at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
    at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
    at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
    at java.base/java.util.Objects.checkIndex(Objects.java:373)
    at java.base/java.util.ArrayList.get(ArrayList.java:425)

The size of the List to be randomly accessed can be obtained with the size () method as shown in the sample code that ends normally. If you can always get only one record from the database based on a unique key, use the size () method without checking the size of the List, such as testList.get (0); It is allowed to get the target value in the process.

The important point is to clarify the accessible range so that ʻIndexOutOfBoundsException` does not occur at runtime when performing random access.

--Avoid random access to LinkedList as much as possible

Within the Java List collection, there is a commonly used data structure called LinkedList, which is similar to ʻArrayList. This LinkedList` is a mechanism that holds the context of the stored elements with a link, so it becomes a data structure suitable for inserting new elements into the array and deleting the elements in the array.

However, random access to the LinkedList has the worst performance. If the number of elements to be randomly accessed is about 100, the processing time will be almost the same as when using ʻArrayList, but with LinkedList`, random access is repeated for 100,000 or more large-scale data. That is not realistic in terms of performance.

Therefore, when handling large-scale data with LinkedList in iterative processing, use sequential access such as the extended for statement and forEach method, which will be introduced later, instead of random access using the get method. Please go.

Digression

I introduced the following sample code for random access earlier.

import java.util.List;
import java.util.ArrayList;

public final class TestGet {

    public static void main(String[] args) {
        final List<String> testList = new ArrayList<>(3);
        testList.add("test1");
        testList.add("test2");
        testList.add("test3");

        for (int i = 0, size = testList.size(); i < size; i++) {
            //Get the i-th element of the variable (random access)
            System.out.println(testList.get(i));
        }
    }
}

I thought that the for statement in the above sample code might not be familiar to beginners, so I will leave an explanation. In the sample code above, the for statement can be written as follows.

for (int i = 0; i < testList.size(); i++) {
    // do something
}

In the sample code introduced at the beginning, I tried to get the size of testList by executing the call of thesize ()method in the initialization expression part in the conditional expression part.

However, you should avoid writing the for statement above. This is because the conditional expression part ʻi <testList.size ()of the for statement is executed every time iterative processing is performed, so in the case of the above code, thesize ()method is called by the size oftestList`. It will be. Around 10 or 100 will have little impact on performance, but even small differences can make a big difference.

For example, you can check that the processing of the conditional expression part is executed every time with the following sample code.

public final class Main {

    public static void main(String[] args) throws Exception {
        //Make sure the conditional expression part is executed every time
        for (int i = 0; i < 10 && saySomething(); i++) {
            // do something
        }
    }

    private static boolean saySomething() {
        System.out.println("Hello World!");
        return true;
    }
}

The execution result of the above sample code is output as follows. I wouldn't write code like the one above in my normal development, but I was able to confirm that the saySomething () method of the conditional expression part was executed 10 times.

Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!

From the above, you can write a leaner and more efficient program by finding the number of items to be used in the conditional expression part in the initialization expression part that is executed only once at the start of the for statement. This is a technique that can be applied not only to the size () method in the List collection but also to various situations, so I would like people who aim for a better program to keep in mind every day.

Sequential access using extended for statement

It's been a while since the extended for statement was added as a Java feature, and it's already become the de facto standard for sequential iterative processing of List collections. The for statement is also simpler and more efficient than the one for random access.

Prior to the introduction of the extended for statement, sequential access was achieved by implementing the ʻIterator interface on its own. Sequential access on the ʻIterator interface is complicated and often implemented, and it is rarely used in legacy writing styles, so I will not cover it in detail in this article, but as a knowledge, before the appearance of the extended for statement Keep in mind that ʻIterator` interface was implemented by itself to achieve sequential access.

In addition, the performance degradation when using ʻIndexOutOfBoundsException(out-of-range exception) andLinkedList introduced during random access using the getmethod does not occur with sequential access using theextended for statement`.

Therefore, if you can use the extended for statement, do not repeat the process with random access, and try to write the iterative process using the extended for statement.

Now, if you rewrite the sample code of random access using the get method introduced earlier with sequential access using the extended for statement, it will be as follows.

import java.util.List;
import java.util.ArrayList;

public final class TestEnhancedForStatement {

    public static void main(String[] args) {
        final List<String> testList = new ArrayList<>(3);
        testList.add("test1");
        testList.add("test2");
        testList.add("test3");

        for (String value : testList) {
            //Get the values stored in testList in order from the beginning
            System.out.println(value);
        }
    }
}

The way to read the extended for statement in the above sample code is as follows:" Get the values stored in testList as String type values in order from the beginning and store them in the variable name value. Become. The grammar is similar in other high-level languages such as Python and Ruby, so if you have already touched other high-level languages, there should be no particular difficulty.

And the output result of executing the above sample code is as follows.

test1
test2
test3

Sequential access using the forEach method

With the introduction of the functional interface in JDK1.8, the forEach (Consumer <T>) method for iterating over the List collection has been added. This method is very similar to the forEach (BiConsumer <T, U>) method I introduced earlier in my article [^ 1] on iterating over Map collections. It is now possible to write sequential access processing more concisely and intuitively than the extended for statement.

The basic writing method is as follows.

import java.util.List;
import java.util.ArrayList;

public final class TestForEach {

    public static void main(String[] args) {
        final List<String> testList = new ArrayList<>(3);
        testList.add("test1");
        testList.add("test2");
        testList.add("test3");

        testList.forEach((value) -> {
            //Get the values stored in testList in order from the beginning
            System.out.println(value);
        });
    }
}

The point that seems difficult is the argument, but the argument of the forEach () method is a lambda expression that implements the functional interface Consumer <T>. Consumer <T> is a functional interface that abstracts the operation of receiving only one argument and not returning any value.

I will omit the lambda expression and functional interface because they deviate from the purpose of this article, but when using the forEach () method in List, it is okay if you remember how to write the above sample code.

And the output result of executing the above sample code is as follows.

test1
test2
test3

important point

--The forEach method cannot return a value

As I mentioned earlier in the description of functional interfaces, the forEach method cannot return a value due to the characteristics ofConsumer <T>. Therefore, if you want to return false as a boolean value when some error is detected during the iterative processing of List, consider using the extended for statement.

[^ 1]: [Java] How to get the key and value stored in Map by iterative processing

Recommended Posts

[Java] Various methods to acquire the value stored in List by iterative processing
How to connect the strings in the List separated by commas
How to increment the value of Map in one line in Java
[Java] How to search for a value in an array (or list) with the contains method
Web application structure by Java and processing flow in the presentation layer
Java reference to understand in the figure
[Processing × Java] How to use the loop
Change List <Optional <T >> to Optional <List <T >> in Java
[Java small story] Monitor when a value is added to the List
[Processing × Java] How to use the class
How to get the date in java
[Processing × Java] How to use the function
How to create your own annotation in Java and get the value
Parallel and parallel processing in various languages (Java edition)
[Note] Java: Speed of List processing by purpose
[Java] Judgment by entering characters in the terminal
I want to get the value in Ruby
java iterative processing
How to save a file with the specified extension under the directory specified in Java to the list
[Introduction to Java] List of things that got caught by the 14th day of programming
# 1_JAVA I want to get the index number by specifying one character in the character string.
[Java] How to display the day of the week acquired by LocalDate, DateTimeformatter in Japanese
Simple statistical analysis of monetary value from the list searched by Mercari Java development
List processing to understand with pictures --java8 stream / javaslang-
[Java] How to omit the private constructor in Lombok
Sample code to convert List to List <String> in Java Stream
Read the packet capture obtained by tcpdump in Java
[Java] How to get the maximum value of HashMap
Source used to get the redirect source URL in Java
Java classes and instances to understand in the figure
I tried to implement the Euclidean algorithm in Java
Filter the Java No. 2 Optional list that was useful in business and get the first value
Use JLine when you want to handle keystrokes on the console character by character in Java
Branch processing by the return value of RestTemplate and the status code of ResponseEntity in Spring Boot
Various threads in java
Java random, various processing
How to get the class name / method name running in Java
[Java, stream] Sort object list in Japanese by property name
Display all in Iterator by iterative processing by while in ArrayList array
Refer to C ++ in the Android Studio module (Java / kotlin)
Easy way to check method / field list in Java REPL
[Android, Java] Convenient method to calculate the difference in days
How to retrieve the hash value in an array in Ruby
Create a method to return the tax rate in Java
List processing to understand with pictures --java8 stream / javaslang --bonus
Several ways to concatenate strings separated by commas in Java
[Rails] How to display the list of posts by category
Think about the differences between functions and methods (in Java)
How to derive the last day of the month in Java
How to switch Java in the OpenJDK era on Mac
[Rails] How to display information stored in the database in view
I want to simplify the conditional if-else statement in Java
[Java] I want to check that the elements in the list are null or empty [Collection Utils]
How to change arguments in [Java] method (for those who are confused by passing by value, passing by reference, passing by reference)