Partner – Microsoft – NPI EA (cat = Baeldung)
announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, visit the documentation page.

You can also ask questions and leave feedback on the Azure Container Apps GitHub page.

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

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, you can get started over on the documentation page.

And, you can also ask questions and leave feedback on the Azure Container Apps GitHub page.

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

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag=Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

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 – MongoDB – NPI EA (tag=MongoDB)
announcement - icon

Traditional keyword-based search methods rely on exact word matches, often leading to irrelevant results depending on the user's phrasing.

By comparison, using a vector store allows us to represent the data as vector embeddings, based on meaningful relationships. We can then compare the meaning of the user’s query to the stored content, and retrieve more relevant, context-aware results.

Explore how to build an intelligent chatbot using MongoDB Atlas, Langchain4j and Spring Boot:

>> Building an AI Chatbot in Java With Langchain4j and MongoDB Atlas

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

Accessibility testing is a crucial aspect to ensure that your application is usable for everyone and meets accessibility standards that are required in many countries.

By automating these tests, teams can quickly detect issues related to screen reader compatibility, keyboard navigation, color contrast, and other aspects that could pose a barrier to using the software effectively for people with disabilities.

Learn how to automate accessibility testing with Selenium and the LambdaTest cloud-based testing platform that lets developers and testers perform accessibility automation on over 3000+ real environments:

Automated Accessibility Testing With Selenium

1. Overview

In this tutorial, we’ll discuss the various ways of finding a string among a group of strings using a single expression.

Let’s assume there’s a fruit “Apple” and a group of fruits “Mango”, “Papaya”, “Apple”, “Pineapple”, etc. Now we’ll explore the various ways to see if the string “Apple” is present among the group of fruits.

2. Introduction to the Problem

Before we move on to the next sections covering the single expression solution, let’s look at an implementation with the if condition:

boolean compareWithMultipleStringsUsingIf(String str, String ... strs) {
    for(String s : strs) {
        if (str.equals(s)) {
            return true;
        }
    }
    return false;
}

This is a very basic implementation, perhaps the most popular among all the implementations. We iterate through the array of Strings and return true when the String str matches with any one of the elements in strs.

Let’s see how this works:

@Test
void givenStrings_whenCompareWithMultipleStringsUsingIf_thenSuccess() {
    String presentString = "Apple";
    String notPresentString = "Avocado";

    assertTrue(compareWithMultipleStringsUsingIf(presentString, "Mango", "Papaya", "Pineapple", "Apple"));
    assertFalse(compareWithMultipleStringsUsingIf(notPresentString, "Mango", "Papaya", "Pineapple", "Apple"));
}

We’re finding the presence of the Strings such as “Apple” and “Avacado” in a group of fruits. But this involves multiple lines of code. Hence let’s look at the upcoming sections for solutions involving a single expression.

3. Match With Set

java.util.Set has the contains() method which checks if an element exists in the collection. Hence, we’ll use java.util.Set for our use case with a single expression:

boolean compareWithMultipleStringsUsingSet(String str, String ... strs) {
    return Set.of(strs).contains(str);
}

With a single expression, we’ve initialized a Set and then used the contains() method to see if str is present in the Set. However, we cannot implement a single expression case-insensitive matching method using Set.

Let’s test the method compareWithMultipleStringsUsingSet():

@Test
void givenStrings_whenCompareWithMultipleStringsUsingSet_thenSuccess() {
    String presentString = "Apple";
    String notPresentString = "Avocado";

    assertTrue(compareWithMultipleStringsUsingSet(presentString, "Mango", "Papaya", "Pineapple", "Apple"));
    assertFalse(compareWithMultipleStringsUsingSet(notPresentString, "Mango", "Papaya", "Pineapple", "Apple"));
}

Just like before, we first pass “Apple” to the method, and it returns true and when we pass “Avocado”, it returns false. Hence, that works pretty well.

4. Match With List

Similar to Set, List also has the contains() method. Hence let’s check out the implementation using List:

boolean compareWithMultipleStringsUsingList(String str, String ... strs) {
    return List.of(strs).contains(str);
}

There isn’t much difference, we’ve replaced Set with List.

Let’s see it in action as well:

@Test
void givenStrings_whenCompareWithMultipleStringsUsingList_thenSuccess() {
    String presentString = "Apple";
    String notPresentString = "Avocado";

    assertTrue(compareWithMultipleStringsUsingList(presentString, "Mango", "Papaya", "Pineapple", "Apple"));
    assertFalse(compareWithMultipleStringsUsingList(notPresentString, "Mango", "Papaya", "Pineapple", "Apple"));
}

The contains() method works as expected and it returns the correct result.

5. Match With Stream

The Stream API encourages the use of declarative statements and hence it can help us in implementing a single expression method:

boolean compareWithMultipleStringsUsingStream(String str, String ... strs) {
    return Arrays.stream(strs).anyMatch(str::equals);
}

In a single expression, we converted the array of Strings into a Stream, and then we used the method anyMatch(). The method anyMatch() is a terminal operation in a Stream pipeline. Each element in the Stream is compared with the String str. However, the anyMatch() method returns the first match.

Let’s check out the method in action:

@Test
void givenStrings_whenCompareWithMultipleStringsUsingStream_thenSuccess() {
    String presentString = "Apple";
    String notPresentString = "Avocado";

    assertTrue(compareWithMultipleStringsUsingStream(presentString, "Mango", "Papaya", "Pineapple", "Apple"));
    assertFalse(compareWithMultipleStringsUsingStream(notPresentString, "Mango", "Papaya", "Pineapple", "Apple"));
}

The method works as expected with “Apple” and “Avocado” as the first argument, returning true and false respectively.

Let’s see a case-insensitive version using Stream:

boolean compareCaseInsensitiveWithMultipleStringsUsingStream(String str, String ... strs) {
    return Arrays.stream(strs).anyMatch(str::equalsIgnoreCase);
}

Unlike the earlier version we had to call the equalsIgnoreCase() method as a predicate to anyMatch().

We can now take a look at the method in action:

@Test
void givenStrings_whenCompareCaseInsensitiveWithMultipleStringsUsingStream_thenSuccess() {
    String presentString = "APPLE";
    String notPresentString = "AVOCADO";

    assertTrue(compareCaseInsensitiveWithMultipleStringsUsingStream(presentString, "Mango", "Papaya", "Pineapple", "Apple"));
    assertFalse(compareCaseInsensitiveWithMultipleStringsUsingStream(notPresentString, "Mango", "Papaya", "Pineapple", "Apple"));
}

This time it can find out “APPLE” among “Mango”, “Papaya”, “Pineapple”, and “Apple”.

6. Match With StringUtils

Before we can use the class StringUtils from the commons-lang3 library, let’s first update the pom.xml with its Maven dependency:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.13.0</version>
</dependency>

Now, let’s use the class StringUtils:

boolean compareWithMultipleStringsUsingStringUtils(String str, String ... strs) {
    return StringUtils.equalsAny(str, strs);
}

The method equalsAny() in StringUtils helps implement our use case in a single expression.

Let’s see the method in action:

@Test
void givenStrings_whenCompareWithMultipleStringsUsingStringUtils_thenSuccess() {
    String presentString = "Apple";
    String notPresentString = "Avocado";

    assertTrue(compareWithMultipleStringsUsingStringUtils(presentString, "Mango", "Papaya", "Pineapple", "Apple"));
    assertFalse(compareWithMultipleStringsUsingStringUtils(notPresentString, "Mango", "Papaya", "Pineapple", "Apple"));
}

This also works as expected, returning true and false when “Apple” and “Mango” are passed to the method, respectively.

Let’s take a look at the case-insensitive version of the method as well:

boolean compareCaseInsensitiveWithMultipleStringsUsingStringUtils(String str, String ... strs) {
    return StringUtils.equalsAnyIgnoreCase(str, strs);
}

Instead of the method equalsAny() we used the method equalsAnyIgnoreCase() of StringUtils.

Let’s see how the method works:

@Test
void givenStrings_whenCompareCaseInsensitiveWithMultipleStringsUsingStringUtils_thenSuccess() {
    String presentString = "APPLE";
    String notPresentString = "AVOCADO";

    assertTrue(compareCaseInsensitiveWithMultipleStringsUsingStringUtils(presentString, "Mango", "Papaya", "Pineapple", "Apple"));
    assertFalse(compareCaseInsensitiveWithMultipleStringsUsingStringUtils(notPresentString, "Mango", "Papaya", "Pineapple", "Apple"));
}

We could successfully find the String “APPLE” among the group of fruits.

7. Match With ArrayUtils

Furthermore, we’ll see another class ArrayUtils from the same commons-lang library:

boolean compareWithMultipleStringsUsingArrayUtils(String str, String ... strs) {
    return ArrayUtils.contains(strs, str);
}

ArrayUtils is a utility class that helps to check if an element is present in an array of objects. Hence, we exploited it to help us implement our use case involving Strings. Unfortunately, ArrayUtils doesn’t provide any method to find a String object in a case-insensitive way. Hence we cannot do a single expression implementation for the same.

Let’s see how the method compareWithAnyUsingArrayUtils() works:

@Test
void givenStrings_whenCompareWithMultipleStringsUsingArrayUtils_thenSuccess() {
    String presentString = "Apple";
    String notPresentString = "Avocado";

    assertTrue(compareWithMultipleStringsUsingArrayUtils(presentString, "Mango", "Papaya", "Pineapple", "Apple"));
    assertFalse(compareWithMultipleStringsUsingArrayUtils(notPresentString, "Mango", "Papaya", "Pineapple", "Apple"));
}

Quite unsurprisingly, it works as well.

8. Match With Regular Expression

Regular expression helps find patterns and hence we’ll use it for our use case:

boolean compareWithMultipleStringsUsingRegularExpression(String str, String ... strs) {
    return str.matches(String.join("|", strs));
}

The method String.join() creates a pipe-delimited list of Strings, for example, Mango|Papaya|Pineapple|Apple which is used as a regular expression pattern. In a single expression, we created the regular expression pattern with the array of Strings and then used the method matches() to check if the String str has the pattern.

Time to see the method in action:

@Test
void givenStrings_whenCompareWithMultipleStringsUsingRegularExpression_thenSuccess() {
    String presentString = "Apple";
    String notPresentString = "Avocado";

    assertTrue(compareWithMultipleStringsUsingRegularExpression(presentString, "Mango", "Papaya", "Pineapple", "Apple"));
    assertFalse(compareWithMultipleStringsUsingRegularExpression(notPresentString, "Mango", "Papaya", "Pineapple", "Apple"));
}

The method returns true for the argument “Mango” and false for “Avocado”. Hence, we can say it works too. However, regular expressions are always performance-intensive, so it’s better to avoid them.

Now, let’s take a look at the case-insensitive implementation:

boolean compareCaseInsensitiveWithMultipleStringsUsingRegularExpression(String str, String ... strs) {
    return str.matches("(?i)" + String.join("|", strs));
}

We just had to modify the regular expression by prepending it with (?i) to do case-insensitive pattern matching.

Let’s take a look at the method in action:

@Test
void givenStrings_whenCompareCaseInsensitiveUsingRegularExpression_thenSuccess() {
    String presentString = "APPLE";
    String notPresentString = "AVOCADO";

    assertTrue(compareCaseInsensitiveWithMultipleStringsUsingRegularExpression(presentString, "Mango", "Papaya", "Pineapple", "Apple"));
    assertFalse(compareCaseInsensitiveWithMultipleStringsUsingRegularExpression(notPresentString, "Mango", "Papaya", "Pineapple", "Apple"));
}

By using the method now we can find “APPLE” in the provided group of fruits as well.

9. Benchmark

Let’s calculate the average execution time of each of the single expression methods using Java Microbenchmark Harness (JMH).

Let’s take a look at the class configured for carrying out the benchmark:

@State(Scope.Benchmark)
@BenchmarkMode(Mode.AverageTime)
@Warmup(iterations = 2)
@Measurement(iterations = 5)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Fork(value = 1)
public class CompareAnyBenchmark {
    private final String[] groupOfFruits = {"Apple", "Mango", "Dragon Fruit", "Water Melon", "Avocado", "Guava", "Orange"};
    private final String fruit = "Apple";

    @Benchmark
    public boolean compareWithMultipleStringsUsingStringUtils() {
        return StringUtils.equalsAny(fruit, groupOfFruits);
    }

    @Benchmark
    public boolean compareCaseInsensitiveWithMultipleStringsUsingStringUtils() {
        return StringUtils.equalsAnyIgnoreCase(fruit, groupOfFruits);
    }
    //Other benchmark methods...
    public static void main(String[] args) throws Exception {
        Options options = new OptionsBuilder().include(CompareAnyBenchmark.class.getSimpleName())
          .threads(1)
          .shouldFailOnError(true)
          .shouldDoGC(true)
          .jvmArgs("-server")
          .build();
        new Runner(options).run();
    }
}

The annotations at the class level set up the benchmark to measure the average time, in nanoseconds, taken for five runs of each method. Finally, the main() method is for running the benchmark.

Let’s now take a look at the average execution time taken for each of the methods we discussed so far:

Method Name Avg. Time Error(±) Unit
compareWithMultipleStringsUsingArrayUtils() 1.150 0.031 ns/op
compareWithMultipleStringsUsingRegularExpression() 1175.809 177.940 ns/op
compareWithMultipleStringsUsingSet() 96.961 11.943 ns/op
compareWithMultipleStringsUsingList()
28.718 1.612 ns/op
compareWithMultipleStringsUsingStream() 47.266 3.968 ns/op
compareWithMultipleStringsUsingStringUtils 1.507 0.040 ns/op
compareCaseInsensitiveWithMultipleStringsUsingRegularExpression() 1803.497 645.104 ns/op
compareCaseInsensitiveWithMultipleStringsUsingStream() 63.079 56.509 ns/op
compareCaseInsensitiveWithMultipleStringsUsingStringUtils() 1.521 0.077 ns/op

The methods compareCaseInsensitiveWithMultipleStringsUsingRegularExpression() and compareWithMultipleStringsUsingRegularExpression() using regular expressions take the longest to execute. On the other hand, the methods compareWithMultipleStringsUsingArrayUtils(), and compareWithMultipleStringsUsingStringUtils() take the least time to execute.

Without considering any external library, the methods compareWithMultipleStringsUsingStream(), and compareCaseInsensitiveWithMultipleStringsUsingStream() have the best score. Moreover, the performance also doesn’t vary much for case-insensitive searches.

10. Conclusion

In this article, we explored various ways to find the presence of a String in a group of Strings. With java.util.Set, java.util.List, java.util.Stream and regular expressions we didn’t use any external library outside of the JDK. Hence it’s advisable to use them rather than going for external libraries like commons-lang. Moreover, the List implementation is the best choice in the JDK library.

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.

Partner – Microsoft – NPI EA (cat = Baeldung)
announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, visit the documentation page.

You can also ask questions and leave feedback on the Azure Container Apps GitHub page.

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

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, visit the documentation page.

You can also ask questions and leave feedback on the Azure Container Apps GitHub page.

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

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag = Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

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

Partner – MongoDB – NPI EA (tag=MongoDB)
announcement - icon

Traditional keyword-based search methods rely on exact word matches, often leading to irrelevant results depending on the user's phrasing.

By comparison, using a vector store allows us to represent the data as vector embeddings, based on meaningful relationships. We can then compare the meaning of the user’s query to the stored content, and retrieve more relevant, context-aware results.

Explore how to build an intelligent chatbot using MongoDB Atlas, Langchain4j and Spring Boot:

>> Building an AI Chatbot in Java With Langchain4j and MongoDB Atlas

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

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