Question

Initialize a HashSet with Values in Java

javacollectionsconstructorinitializationhashset

Question

How can I create a Java Set containing initial values without calling add() repeatedly?

For example, instead of writing:

Set<String> h = new HashSet<String>();
h.add("a");
h.add("b");

is there a concise one-line approach? This is especially useful when declaring a static final field.

Short Answer

You will learn how to initialize a HashSet from existing values in Java, when to use mutable versus immutable sets, and what final means for a collection reference.

Concept

A HashSet is a Set implementation that stores unique values. Adding the same value more than once does not create duplicates.

To initialize a HashSet with values, first create a collection containing those values, then pass it to the HashSet constructor:

Set<String> letters = new HashSet<>(Arrays.asList("a", "b"));

Arrays.asList("a", "b") creates a list, and new HashSet<>(...) copies its items into a new, mutable HashSet.

This distinction matters:

  • HashSet is mutable: you can later call add, remove, or clear.
  • Set.of(...) (Java 9+) is unmodifiable: its contents cannot be changed after creation.
  • final prevents assigning a variable to a different set; it does not automatically make a mutable set unchangeable.

Mental Model

Think of a Set as a bag with a rule: it can hold each label only once.

Creating an empty HashSet and calling add() is like putting labels into the bag one at a time. Passing Arrays.asList("a", "b") to the constructor is like handing the bag-maker a small list of labels and asking for a bag already filled with them.

final puts a lock on the bag's address, not on the bag's contents. You cannot replace the bag with another bag, but you can still add or remove labels if it is a mutable HashSet.

Take Quiz

Syntax and Examples

Use the collection constructor to create a mutable HashSet with initial values:

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

Set<String> letters = new HashSet<>(Arrays.asList("a", "b"));

Because letters is a HashSet, it can be changed later:

letters.add("c");
System.out.println(letters);

The printed order is not guaranteed because HashSet does not preserve insertion order.

For a static final mutable set:

private static final Set<String> ALLOWED_CODES =
        new HashSet<>(Arrays.asList("A", "B", "C"));

For Java 9 or later, use Set.of when the set should never be modified:

private static final Set<String> ALLOWED_CODES = Set.of("A", "B", "C");

Attempting ALLOWED_CODES.add("D") in the Set.of example throws UnsupportedOperationException.

Step by Step Execution

Consider this code:

Set<String> letters = new HashSet<>(Arrays.asList("a", "b", "a"));
letters.add("c");

System.out.println(letters.size());
System.out.println(letters.contains("a"));

Execution steps:

  1. Arrays.asList("a", "b", "a") creates a list with three positions: a, b, and a.
  2. new HashSet<>(...) copies the list values into a set.
  3. The second "a" is ignored because a set stores unique values.
  4. At this point, letters contains a and b.
  5. letters.add("c") adds a new unique value.
  6. letters.size() returns 3.
  7. letters.contains("a") returns true.

The exact display order may be [a, b, c], [c, a, b], or another order.

Real World Use Cases

Initializing sets with known values is useful when an application needs quick membership checks.

  • Input validation: allowed account types such as "free", "pro", and "enterprise".
  • HTTP handling: methods that may contain a request body, such as "POST", "PUT", and "PATCH".
  • Permissions: roles allowed to access an operation.
  • File processing: supported file extensions such as "csv", "json", and "xml".
  • Filtering data: ignoring known test users, blocked identifiers, or reserved words.

For example:

private static final Set<String> SUPPORTED_EXTENSIONS = Set.of("csv", "json", "xml");

boolean isSupported(String extension) {
    return SUPPORTED_EXTENSIONS.contains(extension.toLowerCase());
}

A set is a good fit here because the important operation is checking whether a value is present.

Take Quiz

Real Codebase Usage

In production code, developers usually expose sets through the Set interface rather than the HashSet implementation:

private static final Set<String> PUBLIC_ROUTES = Set.of("/health", "/login");

This lets the implementation change later without changing code that uses the field.

Prefer immutable constants

For fixed application rules, prefer an unmodifiable set:

private static final Set<String> VALID_STATUSES =
        Set.of("NEW", "ACTIVE", "SUSPENDED");

This prevents accidental changes from elsewhere in the class.

Make a mutable copy when needed

A method can start with defaults and then add values based on configuration:

Set<String> enabledFeatures = new HashSet<>(DEFAULT_FEATURES);

if (isBetaUser) {
    enabledFeatures.add("beta-dashboard");
}

Use a set in validation guard clauses

private static final Set<String> VALID_SORTS = Set.of("name", "date", "price");

void validateSortField(String sortField) {
    if (!VALID_SORTS.contains(sortField)) {
        throw new IllegalArgumentException("Unsupported sort field: " + sortField);
    }
}

A HashSet is commonly selected when the set will be modified or when fast membership checks are needed. For constants, Set.of is often clearer on Java 9+.

Common Mistakes

Expecting final to make a HashSet immutable

This compiles and changes the set:

final Set<String> letters = new HashSet<>(Arrays.asList("a", "b"));
letters.add("c"); // Allowed

final only prevents this reassignment:

letters = new HashSet<>(); // Compile-time error

Use Set.of(...) for an unmodifiable fixed set, or wrap a copy with Collections.unmodifiableSet(...) on older Java versions.

Using Arrays.asList as if it creates a set

Set<String> letters = Arrays.asList("a", "b"); // Does not compile

Arrays.asList returns a List, not a Set. Wrap it in new HashSet<>(...).

Using Set.of when later changes are required

Set<String> letters = Set.of("a", "b");
letters.add("c"); // Throws UnsupportedOperationException

Use this instead when changes are required:

Set<String> letters = new HashSet<>(Set.of("a", "b"));
letters.add("c");

Forgetting that HashSet has no predictable order

Set<String> letters = new HashSet<>(Arrays.asList("a", "b", "c"));

Do not rely on iteration or print order. Use LinkedHashSet when insertion order matters, or TreeSet when sorted order matters.

Using double-brace initialization

Set<String> letters = new HashSet<String>() {{
    add("a");
    add("b");
}};

Although concise, this creates an anonymous inner class and can keep an enclosing object reference in some contexts. Prefer constructors and factory methods instead.

Comparisons

ApproachJava versionMutable?Duplicates allowed?Best use
new HashSet<>(Arrays.asList("a", "b"))Java 5+YesNoA mutable set with initial values
Set.of("a", "b")Java 9+NoNo; duplicates cause an exceptionFixed constants
new HashSet<>(Set.of("a", "b"))Java 9+YesNoMutable copy of concise initial values
new LinkedHashSet<>(Arrays.asList("a", "b"))Java 5+YesNoPreserve insertion order
new TreeSet<>(Arrays.asList("b", "a"))Java 5+YesNoKeep values sorted

HashSet is usually the default mutable set. Choose another set type only when ordering is part of the requirement.

Take Quiz

Cheat Sheet

// Mutable HashSet, Java 5+
Set<String> values = new HashSet<>(Arrays.asList("a", "b"));

// Immutable/unmodifiable set, Java 9+
Set<String> values = Set.of("a", "b");

// Mutable HashSet using Java 9+ factory syntax
Set<String> values = new HashSet<>(Set.of("a", "b"));

// Constant fixed set
private static final Set<String> VALUES = Set.of("a", "b");

// Constant reference to a mutable set
private static final Set<String> VALUES =
        new HashSet<>(Arrays.asList("a", "b"));

Key rules:

  • A Set removes duplicate values.
  • HashSet does not guarantee iteration order.
  • Set.of(...) rejects null values and duplicate values.
  • HashSet permits one null value.
  • final prevents reassignment, not mutation.
  • Prefer declaring variables as Set<T> unless you specifically need HashSet methods.

FAQ

How do I initialize a HashSet in one line in Java?

Use:

Set<String> values = new HashSet<>(Arrays.asList("a", "b"));

Import java.util.Arrays, java.util.HashSet, and java.util.Set.

Can I use Set.of instead of new HashSet?

Yes, on Java 9 or later, if the set should not change:

Set<String> values = Set.of("a", "b");

It returns an unmodifiable set, not a HashSet.

Does static final Set make the set immutable?

No. final means the field cannot refer to a different set. If the set is mutable, its elements can still change. Use Set.of for a fixed set.

What happens if initial HashSet values contain duplicates?

Duplicates are silently removed:

Set<String> values = new HashSet<>(Arrays.asList("a", "a", "b"));
// Contains only "a" and "b"

Can a HashSet contain null?

Yes. A HashSet can contain one null value. Set.of(...) does not permit null and throws NullPointerException if one is supplied.

Why does my HashSet print in a different order?

HashSet does not promise a stable order. Use LinkedHashSet for insertion order or TreeSet for sorted order.

Take Quiz

Mini Project

Description

Create a small file-extension validator. A fixed set stores the extensions your application supports, and a method checks whether a supplied file name uses one of them. This demonstrates initializing a set with values and using fast membership checks.

Goal

Build a validator that accepts .csv, .json, and .xml file names regardless of letter case.

Requirements

Use a static final Set<String> for supported extensions.

Initialize the set with its values at declaration time.

Extract the extension from a file name.

Treat extension matching as case-insensitive.

Return false for a file name with no extension.

Take Quiz

Keep learning

Related questions

View more