eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

Partner – LambdaTest – NPI EA (cat=Testing)
announcement - icon

Regression testing is an important step in the release process, to ensure that new code doesn't break the existing functionality. As the codebase evolves, we want to run these tests frequently to help catch any issues early on.

The best way to ensure these tests run frequently on an automated basis is, of course, to include them in the CI/CD pipeline. This way, the regression tests will execute automatically whenever we commit code to the repository.

In this tutorial, we'll see how to create regression tests using Selenium, and then include them in our pipeline using GitHub Actions:, to be run on the LambdaTest cloud grid:

>> How to Run Selenium Regression Tests With GitHub Actions

Course – LJB – NPI EA (cat = Core Java)
announcement - icon

Code your way through and build up a solid, practical foundation of Java:

>> Learn Java Basics

1. Overview

In this tutorial, we’re going to have a look at different ways to compare arrays in Java. We’ll cover conventional methods, and we’ll also see some examples using lambda expressions.

2. Comparing Arrays

We’re going to compare arrays in Java, and as we know, these are objects. Therefore, let’s refresh some basic concepts:

  • Objects have references and values
  • Two equal references should point to the same value
  • Two different values should have different references
  • Two equal values don’t necessarily have the same references
  • Primitive values only get compared per value
  • String literals only get compared per value

2.1. Comparing Object References

If we have two references pointing to the same array, we should always get a result true in an equals comparison with the == operator.

Let’s look at an example:

String[] planes1 = new String[] { "A320", "B738", "A321", "A319", "B77W", "B737", "A333", "A332" };
String[] planes2 = planes1;

First, we created an array of plane models referenced by planes1. We then create planes2, which references planes1. By doing this, we’re creating two references to the same array in memory. Therefore, the “planes1 == planes2” expression will return true.

For arrays, the equals() method is the same as the == operator. So, planes1.equals(planes2) returns true because both references are referring to the same object. Generally speaking, array1.eqauls(array2) will return true if and only if the expression array1 == array2″ returns true.

Let’s assert if the two references are the same:

assertThat(planes1).isSameAs(planes2);

Let’s now be sure that the values referenced by planes1 are actually the same as those referenced by planes2. Therefore, we can change the array referenced by planes2, and check if the changes have any impact on the array referenced by planes1:

planes2[0] = "747";

To finally see this working, let’s make our assertions:

assertThat(planes1).isSameAs(planes2);
assertThat(planes2[0]).isEqualTo("747");
assertThat(planes1[0]).isEqualTo("747");

With this unit test, we were able to compare two arrays by reference.

However, we’ve only proven that one reference, once assigned to the value of another, will reference the same value.

We’ll now create two different arrays with the same values:

String[] planes1 = new String[] { "A320", "B738", "A321", "A319", "B77W", "B737", "A333", "A332" };
String[] planes2 = new String[] { "A320", "B738", "A321", "A319", "B77W", "B737", "A333", "A332" };

Since they are different objects, we know for sure that they are not the same. We can, therefore, compare them:

assertThat(planes1).isNotSameAs(planes2);

To sum up, in this case, we have two arrays in memory that contain the same String values in exactly the same order. However, not only are the referenced arrays different in content, but the references themselves are also different.

2.2. Comparing Array Lengths

The length of the arrays can be compared regardless of their element types, or whether or not their values are filled in.

Let’s create two arrays:

final String[] planes1 = new String[] { "A320", "B738", "A321", "A319", "B77W", "B737", "A333", "A332" };
final Integer[] quantities = new Integer[] { 10, 12, 34, 45, 12, 43, 5, 2 };

These are two different arrays with different element types. In this data set, we’re registering, as an example, how many airplanes of each model are stored in the warehouse. Let’s now run unit tests on them:

assertThat(planes1).hasSize(8);
assertThat(quantities).hasSize(8);

With this, we’ve proven that both arrays have eight elements and that the length property returns the correct number of elements for each array.

2.3. Comparing Arrays with Arrays.equals

So far we only compared arrays based on their object identities. On the other hand, to check if two arrays are equal in terms of their contents, Java provides the Arrays.equals static method. This method will iterate through the arrays, per position in parallel, and apply the == operator, for every pair of elements.

Let’s create two different arrays with the same String literals in exactly the same order:

String[] planes1 = new String[] { "A320", "B738", "A321", "A319", "B77W", "B737", "A333", "A332" };
String[] planes2 = new String[] { "A320", "B738", "A321", "A319", "B77W", "B737", "A333", "A332" };

And now, let’s assert that they’re equal:

assertThat(Arrays.equals(planes1, planes2)).isTrue();

If we change the order of the values of the second array:

String[] planes1 = new String[] { "A320", "B738", "A321", "A319", "B77W", "B737", "A333", "A332" };
String[] planes2 = new String[] { "B738", "A320", "A321", "A319", "B77W", "B737", "A333", "A332" };

We’ll get a different result:

assertThat(Arrays.equals(planes1, planes2)).isFalse();

2.4. Comparing Arrays with Arrays.deepEquals

Using the == operator is easy if we’re using simple types in Java. These could be primitive types or String literals. A comparison between arrays of Objects can be more complicated. The reason behind this is fully explained in our Arrays.deepEquals article. Let’s see an example.

First, let’s start with a Plane class:

public class Plane {
    private final String name;
    private final String model;

    // getters and setters
}

And, let’s implement the hashCode and equals methods:

@Override
public boolean equals(Object o) {
    if (this == o)
        return true;
    if (o == null || getClass() != o.getClass())
        return false;
    Plane plane = (Plane) o;
    return Objects.equals(name, plane.name) && Objects.equals(model, plane.model);
}

@Override
public int hashCode() {
    return Objects.hash(name, model);
}

Secondly, let’s create the following two-element arrays:

Plane[][] planes1 
  = new Plane[][] { new Plane[]{new Plane("Plane 1", "A320")}, new Plane[]{new Plane("Plane 2", "B738") }};
Plane[][] planes2 
  = new Plane[][] { new Plane[]{new Plane("Plane 1", "A320")}, new Plane[]{new Plane("Plane 2", "B738") }};

Let’s now see if they are true, deeply equal arrays:

assertThat(Arrays.deepEquals(planes1, planes2)).isTrue();

To make sure that our comparison works as  expected, let’s now change the order of our last array:

Plane[][] planes1 
  = new Plane[][] { new Plane[]{new Plane("Plane 1", "A320")}, new Plane[]{new Plane("Plane 2", "B738") }};
Plane[][] planes2 
  = new Plane[][] { new Plane[]{new Plane("Plane 2", "B738")}, new Plane[]{new Plane("Plane 1", "A320") }};

Finally, let’s test if they are indeed not equal anymore:

assertThat(Arrays.deepEquals(planes1, planes2)).isFalse();

2.5. Comparing Arrays with Different Orders of Elements

To check if arrays are equal, regardless of the order of elements, we need to define what makes one instance of our Plane unique. For our case, a different name or model is enough to determine that one plane is different from another. We’ve established this by having already implemented both hashCode and equals methods. This implies that before we can compare our arrays, we should sort them. For that, we need a Comparator:

Comparator<Plane> planeComparator = (o1, o2) -> {
    if (o1.getName().equals(o2.getName())) {
        return o2.getModel().compareTo(o1.getModel());
    }
    return o2.getName().compareTo(o1.getName());
};

In this Comparator, we’re giving priority to the name. If the names are equal, we solve the ambiguity by looking at the model. We compare strings by using the compareTo method of type String.

We want to be able to find if arrays are equal regardless of the sorting order. To do that, let’s now sort our arrays:

Arrays.sort(planes1[0], planeComparator);
Arrays.sort(planes2[0], planeComparator);

And finally, let’s test them:

assertThat(Arrays.deepEquals(planes1, planes2)).isTrue();

Having sorted the arrays in the same order first, we allow the deepEquals method to find if these two arrays are equal.

2.6. Comparing Arrays Lexicographically

Java 9 introduced a brand new method in the Arrays utility class called compare(). As the name implies, this method allows us to compare two arrays lexicographically.

In short, the lexicographic comparison is done element by element and refers to the natural order of the elements, such as numerical order for numbers or alphabetical order for strings.

Typically, if the two arrays have the same length, then the comparison is the result of comparing each pair of elements at the same index within the respective arrays.

So, let’s see it in action:

@Test
void givenSameContents_whenCompare_thenCorrect() {
    String[] array1 = new String[] { "A", "B", "C" };
    String[] array2 = new String[] { "A", "B", "C" };

    assertThat(Arrays.compare(array1, array2)).isEqualTo(0);
}

As shown above, compare() returns zero when the given two arrays are equal lexicographically.

On the other hand, if the two arrays have different lengths, the shorter array is considered a proper prefix of the longer array. The method checks which array is lexicographically less than the other:

@Test
void givenDifferentContents_whenCompare_thenDifferent() {
    String[] array1 = new String[] { "A", "B", "C", "D"};
    String[] array2 = new String[] { "A", "C", "B" };

    assertThat(Arrays.compare(array1, array2)).isLessThan(0);
    assertThat(Arrays.compare(array2, array1)).isGreaterThan(0);
    assertThat(Arrays.compare(array1, null)).isGreaterThan(0);
}

Here, array1 is longer than array2, but it’s still considered the smallest because of the lexicographic comparison at index 1. Lexicographically, “B” is smaller than “C”.

As we can see, the method returns a value greater than zero when the first given array is lexicographically greater than the second one. Otherwise, it returns a value less than zero.

Furthermore, a null is always lexicographically less than a non-null array.

Please note that the Arrays class offers several overloaded compare() versions for comparing arrays holding primitive data such as boolean, byte, char, and int.

3. Conclusion

In this tutorial, we’ve seen different ways of comparing arrays. Secondly, we saw the difference between comparing references and values. In addition, we’ve taken a look into how we can compare arrays deeply. Finally, we saw the difference between a normal compare and a deep compare using equals and deepEquals, respectively.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

eBook Jackson – NPI EA – 3 (cat = Jackson)