Immutable Map in Java with Examples - Java 147

Immutable Map in Java with Examples – Java 147

Immutable Map in Java with Examples

介紹使用 JDK、Guava 以及 Apache Collections 4 來建立無法修改的集合,此集合是線程安全的,記憶效率很高, 由於是不可變的,因此可以毫無問題地傳遞給第三方程式庫,Immutable Map in Java 本篇增加了範例,並透過單元測試來驗證產出結果。

檔案目錄

./
   +- src
       +- test
       |   +- org
       |       +- ruoxue
       |           +- java_147
       |               +- map
       |                   +- ImmutableMapWithExamplesTest.java   

單元測試

Map Immutable Java 提供建立不可變的的集合。

Fruit

建立 Fruit 類別,覆寫 toString ,定義屬性和方法,用來建立一個物件。

	@NoArgsConstructor
	@Getter
	@Setter
	@Builder
	public static class Fruit {

		private String name;
		private double quantity;
		private int type;

		public Fruit(String name, double quantity, int type) {
			this.name = name;
			this.quantity = quantity;
			this.type = type;
		}

		public String toString() {
			ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.JSON_STYLE);
			builder.appendSuper(super.toString());
			builder.append("name", name);
			builder.append("quantity", quantity);
			builder.append("type", type);
			return builder.toString();
		}
	}

Collections_unmodifiableMap

Map Immutable Java 建立一個 Map ,使用 Collections unmodifiableMap 初始化三個元素,為不可變的集合,若操作新增、刪除等方法,會拋出例外。

	@Test
	public void Collections_unmodifiableMap() {
		Fruit grape = new Fruit("Grape", Double.MAX_VALUE, 1);
		Fruit kiwifruit = new Fruit("Kiwifruit", -1, 3);
		Fruit lemon = new Fruit("Lemon", 3, 1);
		Map<String, Fruit> map = new HashMap<String, Fruit>();
		map.put(grape.getName(), grape);
		map.put(kiwifruit.getName(), kiwifruit);
		map.put(lemon.getName(), lemon);
		Map<String, Fruit> result = Collections.unmodifiableMap(map);
		Fruit papaya = new Fruit("Papaya", 101, 2);
		assertThatCode(() -> result.put(papaya.getName(), papaya)).isInstanceOf(UnsupportedOperationException.class);
		System.out.println(result);
		assertThat(result).hasSize(3);
	}
{Grape={"name":"Grape","quantity":1.7976931348623157E308,"type":1}, Kiwifruit={"name":"Kiwifruit","quantity":-1.0,"type":3}, Lemon={"name":"Lemon","quantity":3.0,"type":1}}

Collections_singletonMap

Map Immutable Java 建立一個 Map ,使用 Collections singletonMap 初始化一個元素,只能包含一個元素,為不可變的集合,若操作新增、刪除等方法,會拋出例外。

	@Test
	public void Collections_singletonMap() {
		Fruit grape = new Fruit("Grape", Double.MAX_VALUE, 1);
		Map<String, Fruit> result = Collections.singletonMap(grape.getName(), grape);
		Fruit kiwifruit = new Fruit("Kiwifruit", -1, 3);
		assertThatCode(() -> result.put(kiwifruit.getName(), kiwifruit))
				.isInstanceOf(UnsupportedOperationException.class);
		System.out.println(result);
		assertThat(result).hasSize(1);
	}
{Grape={"name":"Grape","quantity":1.7976931348623157E308,"type":1}}

ImmutableMap_of

Map Immutable Java 建立一個 Map ,使用 Guava ImmutableMap of 初始化三個元素,為不可變的集合,若操作新增、刪除等方法,會拋出例外。

	@Test
	public void ImmutableMap_of() {
		Fruit grape = new Fruit("Grape", Double.MAX_VALUE, 1);
		Fruit kiwifruit = new Fruit("Kiwifruit", -1, 3);
		Fruit lemon = new Fruit("Lemon", 3, 1);
		Map<String, Fruit> map = ImmutableMap.of(grape.getName(), grape, kiwifruit.getName(), kiwifruit,
				lemon.getName(), lemon);
		Fruit papaya = new Fruit("Papaya", 101, 2);
		assertThatCode(() -> map.put(papaya.getName(), papaya)).isInstanceOf(UnsupportedOperationException.class);
		System.out.println(map);
		assertThat(map).hasSize(3);
	}
{Grape={"name":"Grape","quantity":1.7976931348623157E308,"type":1}, Kiwifruit={"name":"Kiwifruit","quantity":-1.0,"type":3}, Lemon={"name":"Lemon","quantity":3.0,"type":1}}

ImmutableMap_copyOf

Map Immutable Java 建立一個 Map ,使用 Guava ImmutableMap copyOf 初始化三個元素,為不可變的集合,若操作新增、刪除等方法,會拋出例外。

	@Test
	public void ImmutableMap_copyOf() {
		Fruit grape = new Fruit("Grape", Double.MAX_VALUE, 1);
		Fruit kiwifruit = new Fruit("Kiwifruit", -1, 3);
		Fruit lemon = new Fruit("Lemon", 3, 1);
		Map<String, Fruit> map = new HashMap<String, Fruit>();
		map.put(grape.getName(), grape);
		map.put(kiwifruit.getName(), kiwifruit);
		map.put(lemon.getName(), lemon);
		Map<String, Fruit> result = ImmutableMap.copyOf(map);
		Fruit papaya = new Fruit("Papaya", 101, 2);
		assertThatCode(() -> result.put(papaya.getName(), papaya)).isInstanceOf(UnsupportedOperationException.class);
		System.out.println(result);
		assertThat(result).hasSize(3);
	}
{Grape={"name":"Grape","quantity":1.7976931348623157E308,"type":1}, Kiwifruit={"name":"Kiwifruit","quantity":-1.0,"type":3}, Lemon={"name":"Lemon","quantity":3.0,"type":1}}

ImmutableMap_builder

Java Immutable Map 建立一個 Map ,使用 Guava ImmutableMap builder 初始化三個元素,為不可變的集合,若操作新增、刪除等方法,會拋出例外。

	@Test
	public void ImmutableMap_builder() {
		Fruit grape = new Fruit("Grape", Double.MAX_VALUE, 1);
		Fruit kiwifruit = new Fruit("Kiwifruit", -1, 3);
		Fruit lemon = new Fruit("Lemon", 3, 1);
		Map<String, Fruit> map = new HashMap<String, Fruit>();
		map.put(grape.getName(), grape);
		map.put(kiwifruit.getName(), kiwifruit);
		map.put(lemon.getName(), lemon);
		Map<String, Fruit> result = ImmutableMap.<String, Fruit>builder().putAll(map).build();
		Fruit papaya = new Fruit("Papaya", 101, 2);
		assertThatCode(() -> result.put(papaya.getName(), papaya)).isInstanceOf(UnsupportedOperationException.class);
		System.out.println(result);
		assertThat(result).hasSize(3);
	}
{Grape={"name":"Grape","quantity":1.7976931348623157E308,"type":1}, Kiwifruit={"name":"Kiwifruit","quantity":-1.0,"type":3}, Lemon={"name":"Lemon","quantity":3.0,"type":1}}

MapUtils_unmodifiableMap

Java Immutable Map 建立一個 Map ,使用 Apache Collections4 套件中的 MapUtils unmodifiableMap 初始化三個元素,為不可變的集合,若操作新增、刪除等方法,會拋出例外。

	@Test
	public void MapUtils_unmodifiableMap() {
		Fruit grape = new Fruit("Grape", Double.MAX_VALUE, 1);
		Fruit kiwifruit = new Fruit("Kiwifruit", -1, 3);
		Fruit lemon = new Fruit("Lemon", 3, 1);
		Map<String, Fruit> map = new HashMap<String, Fruit>();
		map.put(grape.getName(), grape);
		map.put(kiwifruit.getName(), kiwifruit);
		map.put(lemon.getName(), lemon);
		Map<String, Fruit> result = MapUtils.unmodifiableMap(map);
		Fruit papaya = new Fruit("Papaya", 101, 2);
		assertThatCode(() -> result.put(papaya.getName(), papaya)).isInstanceOf(UnsupportedOperationException.class);
		System.out.println(result);
		assertThat(result).hasSize(3);
	}
{Grape={"name":"Grape","quantity":1.7976931348623157E308,"type":1}, Kiwifruit={"name":"Kiwifruit","quantity":-1.0,"type":3}, Lemon={"name":"Lemon","quantity":3.0,"type":1}}

ImmutableMapWithExamplesTest.java

Java Immutable Map 新增單元測試,驗證是否符合預期。

package org.ruoxue.java_147.map;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.junit.Test;

import com.google.common.collect.ImmutableMap;

import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

public class ImmutableMapWithExamplesTest {

	@NoArgsConstructor
	@Getter
	@Setter
	@Builder
	public static class Fruit {

		private String name;
		private double quantity;
		private int type;

		public Fruit(String name, double quantity, int type) {
			this.name = name;
			this.quantity = quantity;
			this.type = type;
		}

		public String toString() {
			ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.JSON_STYLE);
			builder.appendSuper(super.toString());
			builder.append("name", name);
			builder.append("quantity", quantity);
			builder.append("type", type);
			return builder.toString();
		}
	}

	@Test
	public void Collections_unmodifiableMap() {
		Fruit grape = new Fruit("Grape", Double.MAX_VALUE, 1);
		Fruit kiwifruit = new Fruit("Kiwifruit", -1, 3);
		Fruit lemon = new Fruit("Lemon", 3, 1);
		Map<String, Fruit> map = new HashMap<String, Fruit>();
		map.put(grape.getName(), grape);
		map.put(kiwifruit.getName(), kiwifruit);
		map.put(lemon.getName(), lemon);
		Map<String, Fruit> result = Collections.unmodifiableMap(map);
		Fruit papaya = new Fruit("Papaya", 101, 2);
		assertThatCode(() -> result.put(papaya.getName(), papaya)).isInstanceOf(UnsupportedOperationException.class);
		System.out.println(result);
		assertThat(result).hasSize(3);
	}

	@Test
	public void Collections_singletonMap() {
		Fruit grape = new Fruit("Grape", Double.MAX_VALUE, 1);
		Map<String, Fruit> result = Collections.singletonMap(grape.getName(), grape);
		Fruit kiwifruit = new Fruit("Kiwifruit", -1, 3);
		assertThatCode(() -> result.put(kiwifruit.getName(), kiwifruit))
				.isInstanceOf(UnsupportedOperationException.class);
		System.out.println(result);
		assertThat(result).hasSize(1);
	}

	@Test
	public void ImmutableMap_of() {
		Fruit grape = new Fruit("Grape", Double.MAX_VALUE, 1);
		Fruit kiwifruit = new Fruit("Kiwifruit", -1, 3);
		Fruit lemon = new Fruit("Lemon", 3, 1);
		Map<String, Fruit> map = ImmutableMap.of(grape.getName(), grape, kiwifruit.getName(), kiwifruit,
				lemon.getName(), lemon);
		Fruit papaya = new Fruit("Papaya", 101, 2);
		assertThatCode(() -> map.put(papaya.getName(), papaya)).isInstanceOf(UnsupportedOperationException.class);
		System.out.println(map);
		assertThat(map).hasSize(3);
	}

	@Test
	public void ImmutableMap_copyOf() {
		Fruit grape = new Fruit("Grape", Double.MAX_VALUE, 1);
		Fruit kiwifruit = new Fruit("Kiwifruit", -1, 3);
		Fruit lemon = new Fruit("Lemon", 3, 1);
		Map<String, Fruit> map = new HashMap<String, Fruit>();
		map.put(grape.getName(), grape);
		map.put(kiwifruit.getName(), kiwifruit);
		map.put(lemon.getName(), lemon);
		Map<String, Fruit> result = ImmutableMap.copyOf(map);
		Fruit papaya = new Fruit("Papaya", 101, 2);
		assertThatCode(() -> result.put(papaya.getName(), papaya)).isInstanceOf(UnsupportedOperationException.class);
		System.out.println(result);
		assertThat(result).hasSize(3);
	}

	@Test
	public void ImmutableMap_builder() {
		Fruit grape = new Fruit("Grape", Double.MAX_VALUE, 1);
		Fruit kiwifruit = new Fruit("Kiwifruit", -1, 3);
		Fruit lemon = new Fruit("Lemon", 3, 1);
		Map<String, Fruit> map = new HashMap<String, Fruit>();
		map.put(grape.getName(), grape);
		map.put(kiwifruit.getName(), kiwifruit);
		map.put(lemon.getName(), lemon);
		Map<String, Fruit> result = ImmutableMap.<String, Fruit>builder().putAll(map).build();
		Fruit papaya = new Fruit("Papaya", 101, 2);
		assertThatCode(() -> result.put(papaya.getName(), papaya)).isInstanceOf(UnsupportedOperationException.class);
		System.out.println(result);
		assertThat(result).hasSize(3);
	}

	@Test
	public void MapUtils_unmodifiableMap() {
		Fruit grape = new Fruit("Grape", Double.MAX_VALUE, 1);
		Fruit kiwifruit = new Fruit("Kiwifruit", -1, 3);
		Fruit lemon = new Fruit("Lemon", 3, 1);
		Map<String, Fruit> map = new HashMap<String, Fruit>();
		map.put(grape.getName(), grape);
		map.put(kiwifruit.getName(), kiwifruit);
		map.put(lemon.getName(), lemon);
		Map<String, Fruit> result = MapUtils.unmodifiableMap(map);
		Fruit papaya = new Fruit("Papaya", 101, 2);
		assertThatCode(() -> result.put(papaya.getName(), papaya)).isInstanceOf(UnsupportedOperationException.class);
		System.out.println(result);
		assertThat(result).hasSize(3);
	}
}

心得分享

Java Immutable Map Example 提供了幾種不可變集合常見方法的操作範例,在應用上相當廣泛,熟悉 Java Immutable Map 這些方法的操作,像是: Collections.unmodifiableMap 、 ImmutableMap.of 、 MapUtils.unmodifiableMap 等方法,更方便簡易地建立集合。

發佈留言