import "copyrightAndOthers.stg"
import "primitiveEquals.stg"
import "primitiveHashCode.stg"
import "primitiveLiteral.stg"

isTest() ::= "true"

hasTwoPrimitives() ::= "true"

skipBoolean() ::= "true"

targetPath() ::= "org/eclipse/collections/impl/map/primitive"

fileName(primitive1, primitive2, sameTwoPrimitives) ::= "Abstract<primitive1.name><primitive2.name>MapTestCase"

class(primitive1, primitive2, sameTwoPrimitives) ::= <<
<body(primitive1.type, primitive2.type, primitive1.name, primitive2.name)>
>>

body(type1, type2, name1, name2) ::= <<
<copyrightAndOthers()>

package org.eclipse.collections.impl.map.primitive;

import java.util.Arrays;
import java.util.NoSuchElementException;

import org.eclipse.collections.api.<name2>Iterable;
import org.eclipse.collections.api.Lazy<name2>Iterable;
import org.eclipse.collections.api.bag.MutableBag;
import org.eclipse.collections.api.block.function.primitive.<name2>ToObjectFunction;
import org.eclipse.collections.api.factory.primitive.<name1><name2>Maps;
import org.eclipse.collections.api.iterator.<name2>Iterator;
import org.eclipse.collections.api.map.primitive.<name1><name2>Map;
import org.eclipse.collections.api.map.primitive.Immutable<name1><name2>Map;
import org.eclipse.collections.api.map.primitive.Mutable<name1><name2>Map;
import org.eclipse.collections.api.set.primitive.Mutable<name2>Set;
import org.eclipse.collections.api.tuple.primitive.<name1><name2>Pair;
import org.eclipse.collections.impl.bag.mutable.primitive.<name2>HashBag;
import org.eclipse.collections.impl.block.factory.primitive.<name2>Predicates;
import org.eclipse.collections.impl.factory.Bags;
import org.eclipse.collections.impl.factory.Lists;
import org.eclipse.collections.impl.factory.primitive.<name2>Bags;
import org.eclipse.collections.impl.list.mutable.primitive.<name1>ArrayList;
<if(!sameTwoPrimitives)>import org.eclipse.collections.impl.list.mutable.primitive.<name2>ArrayList;<endif>
import org.eclipse.collections.impl.map.mutable.UnifiedMap;
import org.eclipse.collections.impl.map.mutable.primitive.<name1><name2>HashMap;
import org.eclipse.collections.impl.set.mutable.primitive.<name2>HashSet;
<if(!sameTwoPrimitives)>import org.eclipse.collections.impl.set.mutable.primitive.<name1>HashSet;<endif>
import org.eclipse.collections.impl.test.Verify;
import org.eclipse.collections.impl.tuple.primitive.PrimitiveTuples;
import org.junit.Assert;
import org.junit.Test;

/**
 * This file was automatically generated from template file abstractPrimitivePrimitiveMapTestCase.stg.
 */
public abstract class Abstract<name1><name2>MapTestCase
{
    protected final <name1><name2>Map map = this.classUnderTest();

    protected abstract <name1><name2>Map classUnderTest();

    protected abstract <name1><name2>Map newWithKeysValues(<type1> key1, <type2> value1);

    protected abstract <name1><name2>Map newWithKeysValues(<type1> key1, <type2> value1, <type1> key2, <type2> value2);

    protected abstract <name1><name2>Map newWithKeysValues(<type1> key1, <type2> value1, <type1> key2, <type2> value2, <type1> key3, <type2> value3);

    protected abstract <name1><name2>Map newWithKeysValues(<type1> key1, <type2> value1, <type1> key2, <type2> value2, <type1> key3, <type2> value3, <type1> key4, <type2> value4);

    protected abstract <name1><name2>Map getEmptyMap();

    @Test
    public void keySet()
    {
        Verify.assertEmpty(this.getEmptyMap().keySet());
        Assert.assertEquals(<name1>HashSet.newSetWith(<(literal.(type1))("0")>), this.newWithKeysValues(<["0"]:keyValue(); separator=", ">).keySet());
        Assert.assertEquals(<name1>HashSet.newSetWith(<["0", "31", "32"]:(literal.(type1))(); separator=", ">),
                this.newWithKeysValues(<["0", "31", "32"]:keyValue(); separator=", ">).keySet());
    }

    @Test
    public void values()
    {
        Verify.assertEmpty(this.getEmptyMap().values());

        <name1><name2>Map map = this.newWithKeysValues(<["0"]:keyValue(); separator=", ">);
        Verify.assertSize(1, map.values());
        Assert.assertTrue(map.values().contains(<(literal.(type2))("0")>));

        <name1><name2>Map map1 = this.newWithKeysValues(<["0", "31", "32"]:keyValue(); separator=", ">);
        Verify.assertSize(3, map1.values());
        Assert.assertTrue(map1.values().contains(<(literal.(type2))("0")>));
        Assert.assertTrue(map1.values().contains(<(literal.(type2))("31")>));
        Assert.assertTrue(map1.values().contains(<(literal.(type2))("32")>));
    }

    @Test
    public void get()
    {
        Assert.assertEquals(<(wideLiteral.(type2))("0")>, this.map.get(<(literal.(type1))("0")>)<wideDelta.(type2)>);
        Assert.assertEquals(<(wideLiteral.(type2))("31")>, this.map.get(<(literal.(type1))("31")>)<wideDelta.(type2)>);
        Assert.assertEquals(<(wideLiteral.(type2))("32")>, this.map.get(<(literal.(type1))("32")>)<wideDelta.(type2)>);

        Assert.assertEquals(<(wideLiteral.(type2))("0")>, this.map.get(<(literal.(type1))("1")>)<wideDelta.(type2)>);
        Assert.assertEquals(<(wideLiteral.(type2))("0")>, this.map.get(<(literal.(type1))("33")>)<wideDelta.(type2)>);
    }

    @Test
    public void getIfAbsent()
    {
        Assert.assertEquals(<(wideLiteral.(type2))("0")>, this.map.getIfAbsent(<(literal.(type1))("0")>, <(literal.(type2))("5")>)<wideDelta.(type2)>);
        Assert.assertEquals(<(wideLiteral.(type2))("31")>, this.map.getIfAbsent(<(literal.(type1))("31")>, <(literal.(type2))("5")>)<wideDelta.(type2)>);
        Assert.assertEquals(<(wideLiteral.(type2))("32")>, this.map.getIfAbsent(<(literal.(type1))("32")>, <(literal.(type2))("5")>)<wideDelta.(type2)>);
    }

    @Test
    public void getOrThrow()
    {
        Assert.assertEquals(<(wideLiteral.(type2))("0")>, this.map.getOrThrow(<(literal.(type1))("0")>)<wideDelta.(type2)>);
        Assert.assertEquals(<(wideLiteral.(type2))("31")>, this.map.getOrThrow(<(literal.(type1))("31")>)<wideDelta.(type2)>);
        Assert.assertEquals(<(wideLiteral.(type2))("32")>, this.map.getOrThrow(<(literal.(type1))("32")>)<wideDelta.(type2)>);

        Assert.assertThrows(IllegalStateException.class, () -> this.map.getOrThrow(<(literal.(type1))("1")>));
        Assert.assertThrows(IllegalStateException.class, () -> this.map.getOrThrow(<(literal.(type1))("33")>));
    }

    @Test
    public void containsKey()
    {
        Assert.assertTrue(this.map.containsKey(<(literal.(type1))("0")>));
        Assert.assertTrue(this.map.containsKey(<(literal.(type1))("31")>));
        Assert.assertTrue(this.map.containsKey(<(literal.(type1))("32")>));
        Assert.assertFalse(this.map.containsKey(<(literal.(type1))("1")>));
        Assert.assertFalse(this.map.containsKey(<(literal.(type1))("5")>));
        Assert.assertFalse(this.map.containsKey(<(literal.(type1))("35")>));
    }

    @Test
    public void containsValue()
    {
        Assert.assertTrue(this.map.containsValue(<(literal.(type2))("0")>));
        Assert.assertTrue(this.map.containsValue(<(literal.(type2))("31")>));
        Assert.assertTrue(this.map.containsValue(<(literal.(type2))("32")>));
    }

    @Test
    public void contains()
    {
        Assert.assertTrue(this.map.contains(<(literal.(type2))("0")>));
        Assert.assertTrue(this.map.contains(<(literal.(type2))("31")>));
        Assert.assertTrue(this.map.contains(<(literal.(type2))("32")>));
    }

    @Test
    public void containsAll()
    {
        Assert.assertTrue(this.map.containsAll(<["0", "31", "32"]:(literal.(type2))(); separator=", ">));
        Assert.assertFalse(this.map.containsAll(<["0", "31", "35"]:(literal.(type2))(); separator=", ">));
        Assert.assertTrue(this.map.containsAll());
    }

    @Test
    public void containsAll_Iterable()
    {
        Assert.assertTrue(this.map.containsAll(<name2>ArrayList.newListWith(<["0", "31", "32"]:(literal.(type2))(); separator=", ">)));
        Assert.assertFalse(this.map.containsAll(<name2>ArrayList.newListWith(<["0", "31", "35"]:(literal.(type2))(); separator=", ">)));
        Assert.assertTrue(this.map.containsAll(new <name2>ArrayList()));
    }

    @Test
    public void size()
    {
        Assert.assertEquals(0, this.getEmptyMap().size());
        Assert.assertEquals(1, this.newWithKeysValues(<["0"]:keyValue(); separator=", ">).size());
        Assert.assertEquals(1, this.newWithKeysValues(<["1"]:keyValue(); separator=", ">).size());

        Assert.assertEquals(2, this.newWithKeysValues(<["1", "5"]:keyValue(); separator=", ">).size());
        Assert.assertEquals(2, this.newWithKeysValues(<["0", "5"]:keyValue(); separator=", ">).size());
        Assert.assertEquals(3, this.newWithKeysValues(<["1", "0", "5"]:keyValue(); separator=", ">).size());
        Assert.assertEquals(2, this.newWithKeysValues(<["6", "5"]:keyValue(); separator=", ">).size());
    }

    @Test
    public void isEmpty()
    {
        Assert.assertTrue(this.getEmptyMap().isEmpty());
        Assert.assertFalse(this.map.isEmpty());
        Assert.assertFalse(this.newWithKeysValues(<["1"]:keyValue(); separator=", ">).isEmpty());
        Assert.assertFalse(this.newWithKeysValues(<["0"]:keyValue(); separator=", ">).isEmpty());
        Assert.assertFalse(this.newWithKeysValues(<["50"]:keyValue(); separator=", ">).isEmpty());
    }

    @Test
    public void notEmpty()
    {
        Assert.assertFalse(this.getEmptyMap().notEmpty());
        Assert.assertTrue(this.map.notEmpty());
        Assert.assertTrue(this.newWithKeysValues(<["1"]:keyValue(); separator=", ">).notEmpty());
        Assert.assertTrue(this.newWithKeysValues(<["0"]:keyValue(); separator=", ">).notEmpty());
        Assert.assertTrue(this.newWithKeysValues(<["50"]:keyValue(); separator=", ">).notEmpty());
    }

    @Test
    public void testEquals()
    {
        <name1><name2>Map map1 = this.newWithKeysValues(<["0", "1", "32"]:keyValue(); separator=", ">);
        <name1><name2>Map map2 = this.newWithKeysValues(<["32", "0", "1"]:keyValue(); separator=", ">);
        <name1><name2>Map map3 = this.newWithKeysValues(<["0"]:keyValue(); separator=", ">, <(literal.(type1))("1")>, <(literal.(type2))("2")>, <["32"]:keyValue(); separator=", ">);
        <name1><name2>Map map4 = this.newWithKeysValues(<(literal.(type1))("0")>, <(literal.(type2))("1")>, <["1", "32"]:keyValue(); separator=", ">);
        <name1><name2>Map map5 = this.newWithKeysValues(<["0", "1"]:keyValue(); separator=", ">, <(literal.(type1))("32")>, <(literal.(type2))("33")>);
        <name1><name2>Map map6 = this.newWithKeysValues(<(literal.(type1))("50")>, <(literal.(type2))("0")>, <(literal.(type1))("60")>, <(literal.(type2))("1")>, <(literal.(type1))("70")>, <(literal.(type2))("33")>);
        <name1><name2>Map map7 = this.newWithKeysValues(<(literal.(type1))("50")>, <(literal.(type2))("0")>, <(literal.(type1))("60")>, <(literal.(type2))("1")>);
        <name1><name2>Map map8 = this.newWithKeysValues(<["0", "1"]:keyValue(); separator=", ">);
        <name1><name2>Map map9 = this.newWithKeysValues(<["0"]:keyValue(); separator=", ">);

        Verify.assertEqualsAndHashCode(map1, map2);
        Verify.assertPostSerializedEqualsAndHashCode(map1);
        Verify.assertPostSerializedEqualsAndHashCode(map6);
        Verify.assertPostSerializedEqualsAndHashCode(map8);
        Verify.assertPostSerializedEqualsAndHashCode(this.getEmptyMap());
        Assert.assertNotEquals(map1, map3);
        Assert.assertNotEquals(this.getEmptyMap(), map3);
        Assert.assertNotEquals(map9, this.getEmptyMap());
        Assert.assertNotEquals(this.getEmptyMap(), map9);
        Assert.assertNotEquals(<name2>ArrayList.newListWith(<(literal.(type2))("0")>), map9);
        Assert.assertNotEquals(map1, map4);
        Assert.assertNotEquals(map1, map5);
        Assert.assertNotEquals(map7, map6);
        Assert.assertNotEquals(map7, map8);

        Assert.assertEquals(map1, <name1><name2>Maps.mutable.ofAll(map1));
        Assert.assertEquals(map1, <name1><name2>Maps.immutable.ofAll(map1));
    }

    @Test
    public void testHashCode()
    {
        Assert.assertEquals(
                UnifiedMap.newWithKeysValues(<["0", "1", "32"]:keyValue(); separator=", ">).hashCode(),
                this.newWithKeysValues(<["32", "0", "1"]:keyValue(); separator=", ">).hashCode());
        Assert.assertEquals(
                UnifiedMap.newWithKeysValues(<(literal.(type1))("50")>, <(literal.(type2))("0")>, <(literal.(type1))("60")>, <(literal.(type2))("1")>, <(literal.(type1))("70")>, <(literal.(type2))("33")>).hashCode(),
                this.newWithKeysValues(<(literal.(type1))("50")>, <(literal.(type2))("0")>, <(literal.(type1))("60")>, <(literal.(type2))("1")>, <(literal.(type1))("70")>, <(literal.(type2))("33")>).hashCode());
        Assert.assertEquals(UnifiedMap.newMap().hashCode(), this.getEmptyMap().hashCode());
        Assert.assertEquals(UnifiedMap.newWithKeysValues(<(literal.(type1))("1")>, <(literal.(type2))("2")>).hashCode(), this.newWithKeysValues(<(literal.(type1))("1")>, <(literal.(type2))("2")>).hashCode());
    }

    @Test
    public void testToString()
    {
        Assert.assertEquals("{}", this.getEmptyMap().toString());
        Assert.assertEquals("{<(toStringLiteral.(type1))("0")>=<(toStringLiteral.(type2))("0")>}", this.newWithKeysValues(<["0"]:keyValue(); separator=", ">).toString());
        Assert.assertEquals("{<(toStringLiteral.(type1))("1")>=<(toStringLiteral.(type2))("1")>}", this.newWithKeysValues(<["1"]:keyValue(); separator=", ">).toString());
        Assert.assertEquals("{<(toStringLiteral.(type1))("5")>=<(toStringLiteral.(type2))("5")>}", this.newWithKeysValues(<["5"]:keyValue(); separator=", ">).toString());

        <name1><name2>Map map1 = this.newWithKeysValues(<["0", "1"]:keyValue(); separator=", ">);
        Assert.assertTrue(
                map1.toString(),
                "{<(toStringLiteral.(type1))("0")>=<(toStringLiteral.(type2))("0")>, <(toStringLiteral.(type1))("1")>=<(toStringLiteral.(type2))("1")>}".equals(map1.toString())
                        || "{<(toStringLiteral.(type1))("1")>=<(toStringLiteral.(type2))("1")>, <(toStringLiteral.(type1))("0")>=<(toStringLiteral.(type2))("0")>}".equals(map1.toString()));

        <name1><name2>Map map2 = this.newWithKeysValues(<["1", "32"]:keyValue(); separator=", ">);
        Assert.assertTrue(
                map2.toString(),
                "{<(toStringLiteral.(type1))("1")>=<(toStringLiteral.(type2))("1")>, <(toStringLiteral.(type1))("32")>=<(toStringLiteral.(type2))("32")>}".equals(map2.toString())
                        || "{<(toStringLiteral.(type1))("32")>=<(toStringLiteral.(type2))("32")>, <(toStringLiteral.(type1))("1")>=<(toStringLiteral.(type2))("1")>}".equals(map2.toString()));

        <name1><name2>Map map3 = this.newWithKeysValues(<["0", "32"]:keyValue(); separator=", ">);
        Assert.assertTrue(
                map3.toString(),
                "{<(toStringLiteral.(type1))("0")>=<(toStringLiteral.(type2))("0")>, <(toStringLiteral.(type1))("32")>=<(toStringLiteral.(type2))("32")>}".equals(map3.toString())
                        || "{<(toStringLiteral.(type1))("32")>=<(toStringLiteral.(type2))("32")>, <(toStringLiteral.(type1))("0")>=<(toStringLiteral.(type2))("0")>}".equals(map3.toString()));

        <name1><name2>Map map4 = this.newWithKeysValues(<["32", "33"]:keyValue(); separator=", ">);
        Assert.assertTrue(
                map4.toString(),
                "{<(toStringLiteral.(type1))("32")>=<(toStringLiteral.(type2))("32")>, <(toStringLiteral.(type1))("33")>=<(toStringLiteral.(type2))("33")>}".equals(map4.toString())
                        || "{<(toStringLiteral.(type1))("33")>=<(toStringLiteral.(type2))("33")>, <(toStringLiteral.(type1))("32")>=<(toStringLiteral.(type2))("32")>}".equals(map4.toString()));
    }

    @Test
    public void forEach()
    {
        <name1><name2>Map map0 = this.newWithKeysValues(<(literal.(type1))("0")>, <(literal.(type2))("1")>, <(literal.(type1))("3")>, <(literal.(type2))("4")>);
        <type2>[] sum0 = new <type2>[1];
        map0.forEach(each -> sum0[0] += each);
        Assert.assertEquals(<(wideLiteral.(type2))("5")>, sum0[0]<wideDelta.(type2)>);

        <name1><name2>Map map1 = this.newWithKeysValues(<(literal.(type1))("1")>, <(literal.(type2))("2")>, <(literal.(type1))("3")>, <(literal.(type2))("4")>);
        <type2>[] sum1 = new <type2>[1];
        map1.forEach(each -> sum1[0] += each);
        Assert.assertEquals(<(wideLiteral.(type2))("6")>, sum1[0]<wideDelta.(type2)>);

        <name1><name2>Map map01 = this.newWithKeysValues(<(literal.(type1))("0")>, <(literal.(type2))("1")>, <(literal.(type1))("1")>, <(literal.(type2))("2")>);
        <type2>[] sum01 = new <type2>[1];
        map01.forEach(each -> sum01[0] += each);
        Assert.assertEquals(<(wideLiteral.(type2))("3")>, sum01[0]<wideDelta.(type2)>);

        <name1><name2>Map map = this.newWithKeysValues(<(literal.(type1))("3")>, <(literal.(type2))("4")>, <(literal.(type1))("4")>, <(literal.(type2))("5")>);
        <type2>[] sum = new <type2>[1];
        map.forEach(each -> sum[0] += each);
        Assert.assertEquals(<(wideLiteral.(type2))("9")>, sum[0]<wideDelta.(type2)>);

        <name1><name2>Map map2 = this.getEmptyMap();
        <type2>[] sum2 = new <type2>[1];
        map2.forEach(each -> sum2[0] += each);
        Assert.assertEquals(<(wideLiteral.(type2))("0")>, sum2[0]<wideDelta.(type2)>);

        <name1><name2>Map map3 = this.newWithKeysValues(<(literal.(type1))("1")>, <(literal.(type2))("2")>);
        <type2>[] sum3 = new <type2>[1];
        map3.forEach(each -> sum3[0] += each);
        Assert.assertEquals(<(wideLiteral.(type2))("2")>, sum3[0]<wideDelta.(type2)>);
    }

    @Test
    public void forEachValue()
    {
        <name1><name2>Map map0 = this.newWithKeysValues(<(literal.(type1))("0")>, <(literal.(type2))("1")>, <(literal.(type1))("3")>, <(literal.(type2))("4")>);
        <type2>[] sum0 = new <type2>[1];
        map0.forEachValue(each -> sum0[0] += each);
        Assert.assertEquals(<(wideLiteral.(type2))("5")>, sum0[0]<wideDelta.(type2)>);

        <name1><name2>Map map1 = this.newWithKeysValues(<(literal.(type1))("1")>, <(literal.(type2))("2")>, <(literal.(type1))("3")>, <(literal.(type2))("4")>);
        <type2>[] sum1 = new <type2>[1];
        map1.forEachValue(each -> sum1[0] += each);
        Assert.assertEquals(<(wideLiteral.(type2))("6")>, sum1[0]<wideDelta.(type2)>);

        <name1><name2>Map map01 = this.newWithKeysValues(<(literal.(type1))("0")>, <(literal.(type2))("1")>, <(literal.(type1))("1")>, <(literal.(type2))("2")>);
        <type2>[] sum01 = new <type2>[1];
        map01.forEachValue(each -> sum01[0] += each);
        Assert.assertEquals(<(wideLiteral.(type2))("3")>, sum01[0]<wideDelta.(type2)>);

        <name1><name2>Map map = this.newWithKeysValues(<(literal.(type1))("3")>, <(literal.(type2))("4")>, <(literal.(type1))("4")>, <(literal.(type2))("5")>);
        <type2>[] sum = new <type2>[1];
        map.forEachValue(each -> sum[0] += each);
        Assert.assertEquals(<(wideLiteral.(type2))("9")>, sum[0]<wideDelta.(type2)>);

        <name1><name2>Map map2 = this.getEmptyMap();
        <type2>[] sum2 = new <type2>[1];
        map2.forEachValue(each -> sum2[0] += each);
        Assert.assertEquals(<(wideLiteral.(type2))("0")>, sum2[0]<wideDelta.(type2)>);

        <name1><name2>Map map3 = this.newWithKeysValues(<(literal.(type1))("1")>, <(literal.(type2))("2")>);
        <type2>[] sum3 = new <type2>[1];
        map3.forEachValue(each -> sum3[0] += each);
        Assert.assertEquals(<(wideLiteral.(type2))("2")>, sum3[0]<wideDelta.(type2)>);
    }

    @Test
    public void forEachKey()
    {
        <name1><name2>Map map0 = this.newWithKeysValues(<(literal.(type1))("0")>, <(literal.(type2))("1")>, <(literal.(type1))("3")>, <(literal.(type2))("4")>);
        <type1>[] sum0 = new <type1>[1];
        map0.forEachKey(each -> sum0[0] += each);
        Assert.assertEquals(<(wideLiteral.(type1))("3")>, sum0[0]<wideDelta.(type1)>);

        <name1><name2>Map map1 = this.newWithKeysValues(<(literal.(type1))("1")>, <(literal.(type2))("2")>, <(literal.(type1))("3")>, <(literal.(type2))("4")>);
        <type1>[] sum1 = new <type1>[1];
        map1.forEachKey(each -> sum1[0] += each);
        Assert.assertEquals(<(wideLiteral.(type1))("4")>, sum1[0]<wideDelta.(type1)>);

        <name1><name2>Map map01 = this.newWithKeysValues(<(literal.(type1))("0")>, <(literal.(type2))("1")>, <(literal.(type1))("1")>, <(literal.(type2))("2")>);
        <type1>[] sum01 = new <type1>[1];
        map01.forEachKey(each -> sum01[0] += each);
        Assert.assertEquals(<(wideLiteral.(type1))("1")>, sum01[0]<wideDelta.(type1)>);

        <name1><name2>Map map = this.newWithKeysValues(<(literal.(type1))("3")>, <(literal.(type2))("4")>, <(literal.(type1))("4")>, <(literal.(type2))("5")>);
        <type1>[] sum = new <type1>[1];
        map.forEachKey(each -> sum[0] += each);
        Assert.assertEquals(<(wideLiteral.(type1))("7")>, sum[0]<wideDelta.(type1)>);

        <name1><name2>Map map2 = this.getEmptyMap();
        <type1>[] sum2 = new <type1>[1];
        map2.forEachKey(each -> sum2[0] += each);
        Assert.assertEquals(<(wideLiteral.(type1))("0")>, sum2[0]<wideDelta.(type1)>);

        <name1><name2>Map map3 = this.newWithKeysValues(<(literal.(type1))("1")>, <(literal.(type2))("1")>);
        <type1>[] sum3 = new <type1>[1];
        map3.forEachKey(each -> sum3[0] += each);
        Assert.assertEquals(<(wideLiteral.(type1))("1")>, sum3[0]<wideDelta.(type1)>);
    }

    @Test
    public void forEachKeyValue()
    {
        <name1><name2>Map map0 = this.newWithKeysValues(<(literal.(type1))("0")>, <(literal.(type2))("1")>, <(literal.(type1))("3")>, <(literal.(type2))("4")>);
        <type1>[] sumKey0 = new <type1>[1];
        <type2>[] sumValue0 = new <type2>[1];
        map0.forEachKeyValue((<type1> eachKey, <type2> eachValue) ->
        {
            sumKey0[0] += eachKey;
            sumValue0[0] += eachValue;
        });
        Assert.assertEquals(<(wideLiteral.(type1))("3")>, sumKey0[0]<wideDelta.(type1)>);
        Assert.assertEquals(<(wideLiteral.(type2))("5")>, sumValue0[0]<wideDelta.(type2)>);

        <name1><name2>Map map1 = this.newWithKeysValues(<(literal.(type1))("1")>, <(literal.(type2))("2")>, <(literal.(type1))("3")>, <(literal.(type2))("4")>);
        <type1>[] sumKey1 = new <type1>[1];
        <type2>[] sumValue1 = new <type2>[1];
        map1.forEachKeyValue((<type1> eachKey, <type2> eachValue) ->
        {
            sumKey1[0] += eachKey;
            sumValue1[0] += eachValue;
        });
        Assert.assertEquals(<(wideLiteral.(type1))("4")>, sumKey1[0]<wideDelta.(type1)>);
        Assert.assertEquals(<(wideLiteral.(type2))("6")>, sumValue1[0]<wideDelta.(type2)>);

        <name1><name2>Map map01 = this.newWithKeysValues(<(literal.(type1))("0")>, <(literal.(type2))("1")>, <(literal.(type1))("1")>, <(literal.(type2))("2")>);
        <type1>[] sumKey01 = new <type1>[1];
        <type2>[] sumValue01 = new <type2>[1];
        map01.forEachKeyValue((<type1> eachKey, <type2> eachValue) ->
        {
            sumKey01[0] += eachKey;
            sumValue01[0] += eachValue;
        });
        Assert.assertEquals(<(wideLiteral.(type1))("1")>, sumKey01[0]<wideDelta.(type1)>);
        Assert.assertEquals(<(wideLiteral.(type2))("3")>, sumValue01[0]<wideDelta.(type2)>);

        <name1><name2>Map map = this.newWithKeysValues(<(literal.(type1))("3")>, <(literal.(type2))("4")>, <(literal.(type1))("4")>, <(literal.(type2))("5")>);
        <type1>[] sumKey = new <type1>[1];
        <type2>[] sumValue = new <type2>[1];
        map.forEachKeyValue((<type1> eachKey, <type2> eachValue) ->
        {
            sumKey[0] += eachKey;
            sumValue[0] += eachValue;
        });
        Assert.assertEquals(<(wideLiteral.(type1))("7")>, sumKey[0]<wideDelta.(type1)>);
        Assert.assertEquals(<(wideLiteral.(type2))("9")>, sumValue[0]<wideDelta.(type2)>);

        <name1><name2>Map map2 = this.getEmptyMap();
        <type1>[] sumKey2 = new <type1>[1];
        <type2>[] sumValue2 = new <type2>[1];
        map2.forEachKeyValue((<type1> eachKey, <type2> eachValue) ->
        {
            sumKey2[0] += eachKey;
            sumValue2[0] += eachValue;
        });
        Assert.assertEquals(<(wideLiteral.(type1))("0")>, sumKey2[0]<wideDelta.(type1)>);
        Assert.assertEquals(<(wideLiteral.(type2))("0")>, sumValue2[0]<wideDelta.(type2)>);

        <name1><name2>Map map3 = this.newWithKeysValues(<(literal.(type1))("3")>, <(literal.(type2))("5")>);
        <type1>[] sumKey3 = new <type1>[1];
        <type2>[] sumValue3 = new <type2>[1];
        map3.forEachKeyValue((<type1> eachKey, <type2> eachValue) ->
        {
            sumKey3[0] += eachKey;
            sumValue3[0] += eachValue;
        });
        Assert.assertEquals(<(wideLiteral.(type1))("3")>, sumKey3[0]<wideDelta.(type1)>);
        Assert.assertEquals(<(wideLiteral.(type2))("5")>, sumValue3[0]<wideDelta.(type2)>);
    }

    @Test
    public void injectIntoKeyValue()
    {
        <name1><name2>Map map0 = this.newWithKeysValues(<(literal.(type1))("0")>, <(literal.(type2))("1")>, <(literal.(type1))("3")>, <(literal.(type2))("4")>);

        Long sum0 = map0.injectIntoKeyValue(new Long(0), (Long sum, <type1> eachKey, <type2> eachValue) ->
        {
            return new Long((long) (sum + eachKey + eachValue));
        });
        Assert.assertEquals(new Long(8), sum0);

        <name1><name2>Map copy = map0.injectIntoKeyValue(<name1><name2>Maps.mutable.empty(), Mutable<name1><name2>Map::withKeyValue);
        Assert.assertEquals(map0, copy);
    }

    @Test
    public void makeString()
    {
        Assert.assertEquals("", this.getEmptyMap().makeString());
        Assert.assertEquals("", this.getEmptyMap().makeString(", "));
        Assert.assertEquals("[]", this.getEmptyMap().makeString("[", "/", "]"));
        Assert.assertEquals("<(toStringLiteral.(type2))("0")>", this.newWithKeysValues(<keyValue("0")>).makeString());
        Assert.assertEquals("<(toStringLiteral.(type2))("0")>", this.newWithKeysValues(<keyValue("0")>).makeString(", "));
        Assert.assertEquals("[<(toStringLiteral.(type2))("0")>]", this.newWithKeysValues(<keyValue("0")>).makeString("[", "/", "]"));
        Assert.assertEquals("<(toStringLiteral.(type2))("1")>", this.newWithKeysValues(<(literal.(type1))("1")>, <(literal.(type2))("1")>).makeString());
        Assert.assertEquals("<(toStringLiteral.(type2))("5")>", this.newWithKeysValues(<(literal.(type1))("5")>, <(literal.(type2))("5")>).makeString());

        <name1><name2>Map map1 = this.newWithKeysValues(<["0", "1"]:keyValue(); separator=", ">);
        Assert.assertTrue(
                map1.makeString(),
                "<(toStringLiteral.(type2))("0")>, <(toStringLiteral.(type2))("1")>".equals(map1.makeString())
                        || "<(toStringLiteral.(type2))("1")>, <(toStringLiteral.(type2))("0")>".equals(map1.makeString()));

        <name1><name2>Map map2 = this.newWithKeysValues(<(literal.(type1))("1")>, <(literal.(type2))("1")>, <(literal.(type1))("32")>, <(literal.(type2))("32")>);
        Assert.assertTrue(
                map2.makeString("[", "/", "]"),
                "[<(toStringLiteral.(type2))("1")>/<(toStringLiteral.(type2))("32")>]".equals(map2.makeString("[", "/", "]"))
                        || "[<(toStringLiteral.(type2))("32")>/<(toStringLiteral.(type2))("1")>]".equals(map2.makeString("[", "/", "]")));

        <name1><name2>Map map3 = this.newWithKeysValues(<keyValue("0")>, <(literal.(type1))("32")>, <(literal.(type2))("32")>);
        Assert.assertTrue(
                map3.makeString("~"),
                "<(toStringLiteral.(type2))("0")>~<(toStringLiteral.(type2))("32")>".equals(map3.makeString("~"))
                        || "<(toStringLiteral.(type2))("32")>~<(toStringLiteral.(type2))("0")>".equals(map3.makeString("~")));

        <name1><name2>Map map4 = this.newWithKeysValues(<(literal.(type1))("32")>, <(literal.(type2))("32")>, <(literal.(type1))("33")>, <(literal.(type2))("33")>);
        Assert.assertTrue(
                map4.makeString("[", ", ", "]"),
                "[<(toStringLiteral.(type2))("32")>, <(toStringLiteral.(type2))("33")>]".equals(map4.makeString("[", ", ", "]"))
                        || "[<(toStringLiteral.(type2))("33")>, <(toStringLiteral.(type2))("32")>]".equals(map4.makeString("[", ", ", "]")));
    }

    @Test
    public void appendString()
    {
        Appendable appendable = new StringBuilder();
        this.getEmptyMap().appendString(appendable);
        Assert.assertEquals("", appendable.toString());

        this.getEmptyMap().appendString(appendable, "/");
        Assert.assertEquals("", appendable.toString());

        this.getEmptyMap().appendString(appendable, "{", "/", "}");
        Assert.assertEquals("{}", appendable.toString());

        Appendable appendable0 = new StringBuilder();
        this.newWithKeysValues(<keyValue("0")>).appendString(appendable0);
        Assert.assertEquals("<(toStringLiteral.(type2))("0")>", appendable0.toString());

        Appendable appendable01 = new StringBuilder();
        this.newWithKeysValues(<keyValue("0")>).appendString(appendable01, "/");
        Assert.assertEquals("<(toStringLiteral.(type2))("0")>", appendable01.toString());

        Appendable appendable02 = new StringBuilder();
        this.newWithKeysValues(<keyValue("0")>).appendString(appendable02, "{", "/", "}");
        Assert.assertEquals("{<(toStringLiteral.(type2))("0")>}", appendable02.toString());

        Appendable appendable1 = new StringBuilder();
        this.newWithKeysValues(<(literal.(type1))("1")>, <(literal.(type2))("1")>).appendString(appendable1);
        Assert.assertEquals("<(toStringLiteral.(type2))("1")>", appendable1.toString());

        Appendable appendable2 = new StringBuilder();
        this.newWithKeysValues(<(literal.(type1))("5")>, <(literal.(type2))("5")>).appendString(appendable2);
        Assert.assertEquals("<(toStringLiteral.(type2))("5")>", appendable2.toString());

        Appendable appendable3 = new StringBuilder();
        <name1><name2>Map map1 = this.newWithKeysValues(<["0", "1"]:keyValue(); separator=", ">);
        map1.appendString(appendable3);
        Assert.assertTrue(
                appendable3.toString(),
                "<(toStringLiteral.(type2))("0")>, <(toStringLiteral.(type2))("1")>".equals(appendable3.toString())
                        || "<(toStringLiteral.(type2))("1")>, <(toStringLiteral.(type2))("0")>".equals(appendable3.toString()));

        Appendable appendable4 = new StringBuilder();
        <name1><name2>Map map2 = this.newWithKeysValues(<(literal.(type1))("1")>, <(literal.(type2))("1")>, <(literal.(type1))("32")>, <(literal.(type2))("32")>);
        map2.appendString(appendable4, "[", "/", "]");
        Assert.assertTrue(
                appendable4.toString(),
                "[<(toStringLiteral.(type2))("1")>/<(toStringLiteral.(type2))("32")>]".equals(appendable4.toString())
                        || "[<(toStringLiteral.(type2))("32")>/<(toStringLiteral.(type2))("1")>]".equals(appendable4.toString()));

        Appendable appendable5 = new StringBuilder();
        <name1><name2>Map map3 = this.newWithKeysValues(<(literal.(type1))("1")>, <(literal.(type2))("1")>, <(literal.(type1))("32")>, <(literal.(type2))("32")>);
        map3.appendString(appendable5, "[", "/", "]");
        Assert.assertTrue(
                appendable5.toString(),
                "[<(toStringLiteral.(type2))("1")>/<(toStringLiteral.(type2))("32")>]".equals(appendable5.toString())
                        || "[<(toStringLiteral.(type2))("32")>/<(toStringLiteral.(type2))("1")>]".equals(appendable5.toString()));

        Appendable appendable6 = new StringBuilder();
        map1.appendString(appendable6, "/");
        Assert.assertTrue(
                appendable6.toString(),
                "<(toStringLiteral.(type2))("0")>/<(toStringLiteral.(type2))("1")>".equals(appendable6.toString())
                        || "<(toStringLiteral.(type2))("1")>/<(toStringLiteral.(type2))("0")>".equals(appendable6.toString()));
    }

    @Test
    public void select()
    {
        <name1><name2>Map map = this.newWithKeysValues(<["0", "1", "2", "3"]:keyValue(); separator=", ">);
        <name1><name2>Map actual1 = map.select((<type1> key, <type2> value) -> <(equals.(type1))("key", {<(literal.(type1))("1")>})> || <(equals.(type2))("value", {<(literal.(type2))("3")>})>);
        Assert.assertEquals(<name1><name2>HashMap.newWithKeysValues(<(literal.(type1))("1")>, <(literal.(type2))("1")>, <(literal.(type1))("3")>, <(literal.(type2))("3")>), actual1);
        <name1><name2>Map actual2 = map.select((<type1> key, <type2> value) -> <(equals.(type1))("key", {<(literal.(type1))("0")>})> || <(equals.(type2))("value", {<(literal.(type2))("2")>})>);
        Assert.assertEquals(<name1><name2>HashMap.newWithKeysValues(<keyValue("0")>, <(literal.(type1))("2")>, <(literal.(type2))("2")>), actual2);
    }

    @Test
    public void reject()
    {
        <name1><name2>Map map = this.newWithKeysValues(<["0", "1", "2", "3"]:keyValue(); separator=", ">);
        <name1><name2>Map actual1 = map.reject((<type1> key, <type2> value) -> <(equals.(type1))("key", {<(literal.(type1))("1")>})> || <(equals.(type2))("value", {<(literal.(type2))("3")>})>);
        Assert.assertEquals(<name1><name2>HashMap.newWithKeysValues(<keyValue("0")>, <(literal.(type1))("2")>, <(literal.(type2))("2")>), actual1);
        <name1><name2>Map actual2 = map.reject((<type1> key, <type2> value) -> <(equals.(type1))("key", {<(literal.(type1))("0")>})> || <(equals.(type2))("value", {<(literal.(type2))("2")>})>);
        Assert.assertEquals(<name1><name2>HashMap.newWithKeysValues(<(literal.(type1))("1")>, <(literal.(type2))("1")>, <(literal.(type1))("3")>, <(literal.(type2))("3")>), actual2);
    }

    @Test
    public void select_value()
    {
        <name1><name2>Map map = this.newWithKeysValues(<["0", "1", "2", "3"]:keyValue(); separator=", ">);
        <name2>Iterable actual1 = map.select(<name2>Predicates.greaterThan(<(literal.(type2))("1")>));
        Assert.assertEquals(<name2>Bags.immutable.with(<(literal.(type2))("2")>, <(literal.(type2))("3")>), actual1);
        <name2>Iterable actual2 = map.select(<name2>Predicates.lessThan(<(literal.(type2))("2")>));
        Assert.assertEquals(<name2>Bags.immutable.with(<(literal.(type2))("0")>, <(literal.(type2))("1")>), actual2);
    }

    @Test
    public void reject_value()
    {
        <name1><name2>Map map = this.newWithKeysValues(<["0", "1", "2", "3"]:keyValue(); separator=", ">);
        <name2>Iterable actual1 = map.reject(<name2>Predicates.lessThan(<(literal.(type2))("2")>));
        Assert.assertEquals(<name2>Bags.immutable.with(<(literal.(type2))("2")>, <(literal.(type2))("3")>), actual1);
        <name2>Iterable actual2 = map.reject(<name2>Predicates.greaterThan(<(literal.(type2))("1")>));
        Assert.assertEquals(<name2>Bags.immutable.with(<(literal.(type2))("0")>, <(literal.(type2))("1")>), actual2);
    }

    @Test
    public void collect()
    {
        <name1><name2>Map map = this.newWithKeysValues(<["0", "1", "2", "3"]:keyValue(); separator=", ">);

        <name2>ToObjectFunction\<<primitive2.wrapperName>\> function = parameter -> <(castIntToNarrowTypeWithParens.(type2))("parameter + 1")>;
        Assert.assertEquals(Bags.immutable.with(<["1", "2", "3", "4"]:(literal.(type2))(); separator=", ">), map.collect(function));
        Assert.assertEquals(Bags.immutable.empty(), this.getEmptyMap().collect(function));
        Assert.assertEquals(Bags.immutable.with(<(literal.(type2))("2")>), this.newWithKeysValues(<["1"]:keyValue(); separator=", ">).collect(function));
    }

    @Test
    public void count()
    {
        <name1><name2>Map map = this.newWithKeysValues(<["0", "1", "2", "3"]:keyValue(); separator=", ">);
        Assert.assertEquals(2, map.count(<name2>Predicates.greaterThan(<(literal.(type2))("1")>)));
        Assert.assertEquals(2, map.count(<name2>Predicates.lessThan(<(literal.(type2))("2")>)));
    }

    @Test
    public void detectIfNone_value()
    {
        <name1><name2>Map map = this.newWithKeysValues(<["0", "1", "2", "3"]:keyValue(); separator=", ">);
        <type2> resultNotFound = map.detectIfNone(<name2>Predicates.greaterThan(<(literal.(type2))("5")>), <(literal.(type2))("5")>);
        Assert.assertEquals(<(literal.(type2))("5")>, resultNotFound<(wideDelta.(type2))>);

        Assert.assertEquals(<(literal.(type2))("5")>, this.getEmptyMap().detectIfNone(<name2>Predicates.equal(<(literal.(type2))("0")>), <(literal.(type2))("5")>)<(wideDelta.(type2))>);
        Assert.assertEquals(<(literal.(type2))("5")>, this.newWithKeysValues(<["1"]:keyValue(); separator=", ">).detectIfNone(<name2>Predicates.equal(<(literal.(type2))("0")>), <(literal.(type2))("5")>)<(wideDelta.(type2))>);
        Assert.assertEquals(<(literal.(type2))("1")>, this.newWithKeysValues(<["1"]:keyValue(); separator=", ">).detectIfNone(<name2>Predicates.equal(<(literal.(type2))("1")>), <(literal.(type2))("5")>)<(wideDelta.(type2))>);
        Assert.assertEquals(<(literal.(type2))("0")>, map.detectIfNone(<name2>Predicates.equal(<(literal.(type2))("0")>), <(literal.(type2))("5")>)<(wideDelta.(type2))>);
        Assert.assertEquals(<(literal.(type2))("1")>, map.detectIfNone(<name2>Predicates.equal(<(literal.(type2))("1")>), <(literal.(type2))("5")>)<(wideDelta.(type2))>);
        Assert.assertEquals(<(literal.(type2))("2")>, map.detectIfNone(<name2>Predicates.equal(<(literal.(type2))("2")>), <(literal.(type2))("5")>)<(wideDelta.(type2))>);
    }

    @Test
    public void anySatisfy()
    {
        <name1><name2>Map map = this.newWithKeysValues(<["0", "1", "2", "3"]:keyValue(); separator=", ">);
        Assert.assertFalse(this.getEmptyMap().anySatisfy(<name2>Predicates.equal(<(literal.(type2))("0")>)));
        Assert.assertFalse(this.newWithKeysValues(<["1"]:keyValue(); separator=", ">).anySatisfy(<name2>Predicates.equal(<(literal.(type2))("0")>)));
        Assert.assertTrue(this.newWithKeysValues(<["1"]:keyValue(); separator=", ">).anySatisfy(<name2>Predicates.equal(<(literal.(type2))("1")>)));
        Assert.assertTrue(map.anySatisfy(<name2>Predicates.equal(<(literal.(type2))("0")>)));
        Assert.assertTrue(map.anySatisfy(<name2>Predicates.equal(<(literal.(type2))("1")>)));
        Assert.assertTrue(map.anySatisfy(<name2>Predicates.equal(<(literal.(type2))("2")>)));
        Assert.assertFalse(map.anySatisfy(<name2>Predicates.greaterThan(<(literal.(type2))("5")>)));
    }

    @Test
    public void allSatisfy()
    {
        <name1><name2>Map map = this.newWithKeysValues(<["0", "1", "2", "3"]:keyValue(); separator=", ">);
        Assert.assertTrue(this.getEmptyMap().allSatisfy(<name2>Predicates.equal(<(literal.(type2))("0")>)));
        Assert.assertFalse(this.newWithKeysValues(<["1"]:keyValue(); separator=", ">).allSatisfy(<name2>Predicates.equal(<(literal.(type2))("0")>)));
        Assert.assertTrue(this.newWithKeysValues(<["1"]:keyValue(); separator=", ">).allSatisfy(<name2>Predicates.equal(<(literal.(type2))("1")>)));
        Assert.assertFalse(map.allSatisfy(<name2>Predicates.equal(<(literal.(type2))("0")>)));
        Assert.assertFalse(map.allSatisfy(<name2>Predicates.equal(<(literal.(type2))("1")>)));
        Assert.assertFalse(map.allSatisfy(<name2>Predicates.equal(<(literal.(type2))("2")>)));
        Assert.assertTrue(map.allSatisfy(<name2>Predicates.lessThan(<(literal.(type2))("5")>)));
        <name1><name2>Map map1 = this.newWithKeysValues(<["2", "3"]:keyValue(); separator=", ">);
        Assert.assertFalse(map1.allSatisfy(<name2>Predicates.equal(<(literal.(type2))("0")>)));
    }

    @Test
    public void noneSatisfy()
    {
        <name1><name2>Map map = this.newWithKeysValues(<["0", "1", "2", "3"]:keyValue(); separator=", ">);
        Assert.assertTrue(this.getEmptyMap().noneSatisfy(<name2>Predicates.equal(<(literal.(type2))("0")>)));
        Assert.assertTrue(this.newWithKeysValues(<["1"]:keyValue(); separator=", ">).noneSatisfy(<name2>Predicates.equal(<(literal.(type2))("0")>)));
        Assert.assertFalse(this.newWithKeysValues(<["1"]:keyValue(); separator=", ">).noneSatisfy(<name2>Predicates.equal(<(literal.(type2))("1")>)));
        Assert.assertFalse(map.noneSatisfy(<name2>Predicates.equal(<(literal.(type2))("0")>)));
        Assert.assertFalse(map.noneSatisfy(<name2>Predicates.equal(<(literal.(type2))("1")>)));
        Assert.assertFalse(map.noneSatisfy(<name2>Predicates.equal(<(literal.(type2))("2")>)));
        Assert.assertTrue(map.noneSatisfy(<name2>Predicates.lessThan(<(literal.(type2))("0")>)));
    }

    @Test
    public void max()
    {
        <name1><name2>Map map = this.newWithKeysValues(<["0", "1", "2", "3"]:keyValue(); separator=", ">);
        Assert.assertEquals(<(literal.(type2))("3")>, map.max()<(wideDelta.(type2))>);
        Assert.assertEquals(<(literal.(type2))("3")>, this.newWithKeysValues(<["3"]:keyValue(); separator=", ">).max()<(wideDelta.(type2))>);
    }

    @Test
    public void min()
    {
        <name1><name2>Map map = this.newWithKeysValues(<["1", "2", "3", "0"]:keyValue(); separator=", ">);
        Assert.assertEquals(<(literal.(type2))("0")>, map.min()<(wideDelta.(type2))>);
        Assert.assertEquals(<(literal.(type2))("3")>, this.newWithKeysValues(<["3"]:keyValue(); separator=", ">).min()<(wideDelta.(type2))>);
    }

    @Test(expected = NoSuchElementException.class)
    public void max_empty_throws()
    {
        this.getEmptyMap().max();
    }

    @Test(expected = NoSuchElementException.class)
    public void min_empty_throws()
    {
        this.getEmptyMap().min();
    }

    @Test
    public void minIfEmpty()
    {
        Assert.assertEquals(<(wideLiteral.(type2))("5")>, this.getEmptyMap().minIfEmpty(<(literal.(type2))("5")>)<(wideDelta.(type2))>);
        Assert.assertEquals(<(wideLiteral.(type2))("0")>, this.getEmptyMap().minIfEmpty(<(literal.(type2))("0")>)<(wideDelta.(type2))>);
        <name1><name2>Map map = this.newWithKeysValues(<["1", "0", "9", "7"]:keyValue(); separator=", ">);
        Assert.assertEquals(<(wideLiteral.(type2))("0")>, map.minIfEmpty(<(literal.(type2))("5")>)<(wideDelta.(type2))>);
        Assert.assertEquals(<(literal.(type2))("3")>, this.newWithKeysValues(<["3"]:keyValue(); separator=", ">).maxIfEmpty(<(literal.(type2))("5")>)<(wideDelta.(type2))>);
    }

    @Test
    public void maxIfEmpty()
    {
        Assert.assertEquals(<(wideLiteral.(type2))("5")>, this.getEmptyMap().maxIfEmpty(<(literal.(type2))("5")>)<(wideDelta.(type2))>);
        Assert.assertEquals(<(wideLiteral.(type2))("0")>, this.getEmptyMap().maxIfEmpty(<(literal.(type2))("0")>)<(wideDelta.(type2))>);
        <name1><name2>Map map = this.newWithKeysValues(<["1", "0", "9", "7"]:keyValue(); separator=", ">);
        Assert.assertEquals(<(wideLiteral.(type2))("9")>, map.maxIfEmpty(<(literal.(type2))("5")>)<(wideDelta.(type2))>);
        Assert.assertEquals(<(literal.(type2))("3")>, this.newWithKeysValues(<["3"]:keyValue(); separator=", ">).minIfEmpty(<(literal.(type2))("5")>)<(wideDelta.(type2))>);
    }

    @Test
    public void sum()
    {
        <name1><name2>Map map = this.newWithKeysValues(<["0", "1", "2", "3"]:keyValue(); separator=", ">);
        Assert.assertEquals(<(literal.(type2))("6")>, map.sum()<(wideDelta.(type2))>);
        <name1><name2>Map map2 = this.newWithKeysValues(<["2", "3", "4"]:keyValue(); separator=", ">);
        Assert.assertEquals(<(literal.(type2))("9")>, map2.sum()<(wideDelta.(type2))>);
        <name1><name2>Map map3 = this.newWithKeysValues(<["2"]:keyValue(); separator=", ">);
        Assert.assertEquals(<(literal.(type2))("2")>, map3.sum()<(wideDelta.(type2))>);
    }

    @Test
    public void average()
    {
        <name1><name2>Map map = this.newWithKeysValues(<["0", "1", "2", "3"]:keyValue(); separator=", ">);
        Assert.assertEquals(1.5, map.average(), 0.0);
        <name1><name2>Map map1 = this.newWithKeysValues(<["1"]:keyValue(); separator=", ">);
        Assert.assertEquals(1.0, map1.average(), 0.0);
    }

    @Test(expected = ArithmeticException.class)
    public void averageThrowsOnEmpty()
    {
        this.getEmptyMap().average();
    }

    @Test
    public void median()
    {
        <name1><name2>Map map = this.newWithKeysValues(<["0", "1", "2", "3"]:keyValue(); separator=", ">);
        Assert.assertEquals(1.5, map.median(), 0.0);
        <name1><name2>Map map2 = this.newWithKeysValues(<["0", "1", "2"]:keyValue(); separator=", ">);
        Assert.assertEquals(1.0, map2.median(), 0.0);
        <name1><name2>Map map3 = this.newWithKeysValues(<["1"]:keyValue(); separator=", ">);
        Assert.assertEquals(1.0, map3.median(), 0.0);
    }

    @Test(expected = ArithmeticException.class)
    public void medianThrowsOnEmpty()
    {
        this.getEmptyMap().median();
    }

    @Test
    public void toList()
    {
        Assert.assertEquals(<name2>ArrayList.newListWith(<(literal.(type2))("0")>), this.newWithKeysValues(<keyValue("0")>).toList());
        Assert.assertEquals(<name2>ArrayList.newListWith(<(literal.(type2))("1")>), this.newWithKeysValues(<(literal.(type1))("1")>, <(literal.(type2))("1")>).toList());
        Assert.assertEquals(<name2>ArrayList.newListWith(<(literal.(type2))("2")>), this.newWithKeysValues(<(literal.(type1))("2")>, <(literal.(type2))("2")>).toList());
        Assert.assertTrue(this.newWithKeysValues(<["2", "3"]:keyValue(); separator=", ">).toList().equals(<name2>ArrayList.newListWith(<["2", "3"]:(literal.(type2))(); separator=", ">))
                || this.newWithKeysValues(<["2", "3"]:keyValue(); separator=", ">).toList().equals(<name2>ArrayList.newListWith(<["3", "2"]:(literal.(type2))(); separator=", ">)));
    }

    @Test
    public void toSortedList()
    {
        <name1><name2>Map map = this.newWithKeysValues(<["0", "1", "2", "3"]:keyValue(); separator=", ">);
        Assert.assertEquals(<name2>ArrayList.newListWith(<["0", "1", "2", "3"]:(literal.(type2))(); separator=", ">), map.toSortedList());
        Assert.assertEquals(<name2>ArrayList.newListWith(), this.getEmptyMap().toSortedList());
        Assert.assertEquals(<name2>ArrayList.newListWith(<(literal.(type2))("1")>), this.newWithKeysValues(<["1"]:keyValue(); separator=", ">).toSortedList());
    }

    @Test
    public void toSet()
    {
        <name1><name2>Map map = this.newWithKeysValues(<["0", "1", "2", "3"]:keyValue(); separator=", ">);
        Assert.assertEquals(<name2>HashSet.newSetWith(<["0", "1", "2", "3"]:(literal.(type2))(); separator=", ">), map.toSet());
        Assert.assertEquals(<name2>HashSet.newSetWith(), this.getEmptyMap().toSet());
        Assert.assertEquals(<name2>HashSet.newSetWith(<(literal.(type2))("1")>), this.newWithKeysValues(<["1"]:keyValue(); separator=", ">).toSet());
    }

    @Test
    public void toBag()
    {
        <name1><name2>Map map = this.newWithKeysValues(<["0", "1", "2", "3"]:keyValue(); separator=", ">);
        Assert.assertEquals(<name2>HashBag.newBagWith(<["0", "1", "2", "3"]:(literal.(type2))(); separator=", ">), map.toBag());
        Assert.assertEquals(<name2>HashBag.newBagWith(), this.getEmptyMap().toBag());
        Assert.assertEquals(<name2>HashBag.newBagWith(<(literal.(type2))("1")>), this.newWithKeysValues(<["1"]:keyValue(); separator=", ">).toBag());
    }

    @Test
    public void <type2>Iterator()
    {
        Mutable<name2>Set expected = <name2>HashSet.newSetWith(<(literal.(type2))("0")>, <(literal.(type2))("31")>, <(literal.(type2))("32")>);
        Mutable<name2>Set actual = <name2>HashSet.newSetWith();

        <name2>Iterator iterator = this.map.<type2>Iterator();
        Assert.assertTrue(iterator.hasNext());
        actual.add(iterator.next());
        Assert.assertTrue(iterator.hasNext());
        actual.add(iterator.next());
        Assert.assertTrue(iterator.hasNext());
        actual.add(iterator.next());
        Assert.assertFalse(iterator.hasNext());

        Assert.assertEquals(expected, actual);
        Assert.assertThrows(NoSuchElementException.class, iterator::next);
        Assert.assertThrows(NoSuchElementException.class, () -> this.getEmptyMap().<type2>Iterator().next());
    }

    @Test
    public void asLazy()
    {
        Lazy<name2>Iterable lazy = this.map.asLazy();
        Assert.assertTrue(lazy.toList().containsAll(<(literal.(type2))("0")>, <(literal.(type2))("31")>, <(literal.(type2))("32")>));
    }

    @Test
    public void keysView()
    {
        Assert.assertEquals(<name1>ArrayList.newListWith(<(literal.(type1))("0")>, <(literal.(type1))("31")>, <(literal.(type1))("32")>), this.map.keysView().toSortedList());
    }

    @Test
    public void keyValuesView()
    {
        MutableBag\<<name1><name2>Pair> expected = Bags.mutable.of();
        this.map.forEachKeyValue((<type1> key, <type2> value) -> expected.add(PrimitiveTuples.pair(key, value)));
        Assert.assertEquals(expected, this.map.keyValuesView().toBag());
    }

    @Test
    public void toSortedArray()
    {
        Assert.assertTrue(Arrays.equals(new <type2>[]{<(literal.(type2))("0")>, <(literal.(type2))("31")>, <(literal.(type2))("32")>}, this.map.toSortedArray()));
    }

    @Test
    public void toArray()
    {
        <name1><name2>Map map = this.newWithKeysValues(<["1", "2"]:keyValue(); separator=", ">);
        <type2>[] array = map.toArray();
        Assert.assertTrue(Arrays.equals(new <type2>[]{<(literal.(type2))("1")>, <(literal.(type2))("2")>}, array)
                || Arrays.equals(new <type2>[]{<(literal.(type2))("2")>, <(literal.(type2))("1")>}, array));
        Assert.assertEquals(0, this.getEmptyMap().toArray().length);
        Assert.assertTrue(Arrays.equals(new <type2>[]{<(literal.(type2))("1")>}, this.newWithKeysValues(<["1"]:keyValue(); separator=", ">).toArray()));
    }

    @Test
    public void toImmutable()
    {
        Assert.assertEquals(this.classUnderTest(), this.classUnderTest().toImmutable());
        Verify.assertInstanceOf(Immutable<name1><name2>Map.class, this.classUnderTest().toImmutable());
    }

    @Test
    public void chunk()
    {
        <name2>Iterable iterable = this.newWithKeysValues(<["1", "2", "3"]:keyValue(); separator=", ">);
        Assert.assertEquals(
                Lists.mutable.with(
                        <name2>Bags.mutable.with(<["1"]:(literal.(type2))(); separator=", ">),
                        <name2>Bags.mutable.with(<["2"]:(literal.(type2))(); separator=", ">),
                        <name2>Bags.mutable.with(<["3"]:(literal.(type2))(); separator=", ">)).toSet(),
                iterable.chunk(1).toSet());
        Assert.assertTrue(
                Lists.mutable.with(
                        <name2>Bags.mutable.with(<["1", "2"]:(literal.(type2))(); separator=", ">),
                        <name2>Bags.mutable.with(<["3"]:(literal.(type2))(); separator=", ">)).toSet().equals(iterable.chunk(2).toSet())
                || Lists.mutable.with(
                        <name2>Bags.mutable.with(<["2", "3"]:(literal.(type2))(); separator=", ">),
                        <name2>Bags.mutable.with(<["1"]:(literal.(type2))(); separator=", ">)).toSet().equals(iterable.chunk(2).toSet())
                || Lists.mutable.with(
                        <name2>Bags.mutable.with(<["1", "3"]:(literal.(type2))(); separator=", ">),
                        <name2>Bags.mutable.with(<["2"]:(literal.(type2))(); separator=", ">)).toSet().equals(iterable.chunk(2).toSet()));
        Assert.assertEquals(
                Lists.mutable.with(
                        <name2>Bags.mutable.with(<["1", "2", "3"]:(literal.(type2))(); separator=", ">)).toSet(),
                iterable.chunk(3).toSet());
        Assert.assertEquals(
                Lists.mutable.with(<name2>Bags.mutable.with(<["1", "2", "3"]:(literal.(type2))(); separator=", ">)).toSet(),
                iterable.chunk(4).toSet());
        Assert.assertEquals(
                Lists.mutable.with(<name2>Bags.mutable.with(<["1"]:(literal.(type2))(); separator=", ">)).toSet(),
                this.newWithKeysValues(<["1"]:keyValue(); separator=", ">).chunk(1).toSet());

        Verify.assertIterablesEqual(Lists.mutable.empty(), this.getEmptyMap().chunk(1));

        Assert.assertThrows(IllegalArgumentException.class, () -> iterable.chunk(0));
        Assert.assertThrows(IllegalArgumentException.class, () -> iterable.chunk(-1));
        Assert.assertThrows(IllegalArgumentException.class, () -> this.newWithKeysValues(<["1"]:keyValue(); separator=", ">).chunk(-1));
    }
}

>>

keyValue(value) ::= <<
<(literal.(type1))(value)>, <(literal.(type2))(value)>
>>
