Skip to content

Commit

Permalink
Add OrderedSet interface and implementation, and extend OrderedMap to…
Browse files Browse the repository at this point in the history
… implement SequencedMap.
  • Loading branch information
neilcsmith-net committed May 17, 2024
1 parent dbe6d90 commit f1b5d5e
Show file tree
Hide file tree
Showing 6 changed files with 470 additions and 23 deletions.
10 changes: 7 additions & 3 deletions praxiscore-api/src/main/java/org/praxislive/core/OrderedMap.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2023 Neil C Smith.
* Copyright 2024 Neil C Smith.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 3 only, as
Expand All @@ -23,6 +23,7 @@

import java.util.List;
import java.util.Map;
import java.util.SequencedMap;
import java.util.stream.Stream;

/**
Expand All @@ -32,7 +33,7 @@
* @param <K> key type
* @param <V> value type
*/
public sealed interface OrderedMap<K, V> extends Map<K, V> permits OrderedMapImpl {
public sealed interface OrderedMap<K, V> extends SequencedMap<K, V> permits OrderedMapImpl {

/**
* A {@link List} containing the keys of this OrderedMap.
Expand All @@ -47,6 +48,9 @@ public sealed interface OrderedMap<K, V> extends Map<K, V> permits OrderedMapImp
*/
public List<K> keys();

@Override
public OrderedMap<K, V> reversed();

/**
* Compares the provided object with this map for equality in accordance
* with the specification of {@link Map#equals(java.lang.Object)}.
Expand Down Expand Up @@ -204,7 +208,7 @@ public static <K, V> OrderedMap<K, V> ofEntries(Map.Entry<? extends K, ? extends
* @return an ordered map copy of the provided map
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public static <K, V> OrderedMap<K, V> copyOf(Map<K, V> map) {
public static <K, V> OrderedMap<K, V> copyOf(Map<? extends K, ? extends V> map) {
if (map instanceof OrderedMapImpl) {
return (OrderedMap<K, V>) map;
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2023 Neil C Smith.
* Copyright 2024 Neil C Smith.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 3 only, as
Expand Down Expand Up @@ -48,11 +48,6 @@ public List<K> keys() {
return keys;
}

@Override
public void clear() {
map.clear();
}

@Override
public boolean containsKey(Object key) {
return map.containsKey(key);
Expand Down Expand Up @@ -116,18 +111,8 @@ public int size() {
}

@Override
public V put(K key, V value) {
throw new UnsupportedOperationException();
}

@Override
public void putAll(Map<? extends K, ? extends V> m) {
throw new UnsupportedOperationException();
}

@Override
public V remove(Object key) {
throw new UnsupportedOperationException();
public OrderedMap<K, V> reversed() {
return new OrderedMapImpl<>(List.copyOf(keys.reversed()), map);
}

@Override
Expand Down Expand Up @@ -178,4 +163,24 @@ public String toString() {
.collect(Collectors.joining(", ", "{", "}"));
}

@Override
public void clear() {
throw new UnsupportedOperationException();
}

@Override
public V put(K key, V value) {
throw new UnsupportedOperationException();
}

@Override
public void putAll(Map<? extends K, ? extends V> m) {
throw new UnsupportedOperationException();
}

@Override
public V remove(Object key) {
throw new UnsupportedOperationException();
}

}
184 changes: 184 additions & 0 deletions praxiscore-api/src/main/java/org/praxislive/core/OrderedSet.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2024 Neil C Smith.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 3 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* version 3 for more details.
*
* You should have received a copy of the GNU Lesser General Public License version 3
* along with this work; if not, see http://www.gnu.org/licenses/
*
*
* Please visit https://www.praxislive.org if you need additional information or
* have any questions.
*/
package org.praxislive.core;

import java.util.List;
import java.util.Set;
import java.util.SequencedSet;

/**
* A {@link Set} with consistent order of entries. All static factory methods
* produce unmodifiable sets.
*
* @param <E> value type
*/
public sealed interface OrderedSet<E> extends SequencedSet<E> permits OrderedSetImpl {

/**
* A {@link List} containing all the values of this OrderedSet.
* <p>
* Because Set equality ignores order, code needing to verify whether an
* OrderedSet contains the same values in the same order should also check
* for equality of the values list.
*
* @return values as list
*/
public List<E> values();

@Override
public OrderedSet<E> reversed();

/**
* Compares the provided object with this map for equality in accordance
* with the specification of {@link Map#equals(java.lang.Object)}.
* <p>
* Because Map equality does not depends on order, code needing to verify
* whether an OrderedMap contains the same mappings in the same order should
* also check for equality of the {@link #keys()} list.
*
* @param obj object to compare
* @return true if the object is a map containing the same mappings, not
* necessarily in the same order
*/
@Override
public boolean equals(Object obj);

/**
* Returns an empty OrderedSet.
*
* @param <E> value type
* @return empty OrderedSet
*/
public static <E> OrderedSet<E> of() {
return new OrderedSetImpl<>(Set.of(), List.of());
}

/**
* Returns an OrderedSet with a single element.
*
* @param <E> element type
* @param element element
* @return an OrderedSet of the provided element
* @throws NullPointerException if element is null
*/
public static <E> OrderedSet<E> of(E element) {
return new OrderedSetImpl<>(Set.of(element), List.of(element));
}

/**
* Returns an OrderedSet with two elements.
*
* @param <E> element type
* @param e1 first element
* @param e2 second element
* @return an OrderedSet of the provided elements
* @throws NullPointerException if any elements are null
* @throws IllegalArgumentException if any elements are duplicated
*/
public static <E> OrderedSet<E> of(E e1, E e2) {
return new OrderedSetImpl<>(Set.of(e1, e2), List.of(e1, e2));
}

/**
* Returns an OrderedSet with three elements.
*
* @param <E> element type
* @param e1 first element
* @param e2 second element
* @param e3 third element
* @return an OrderedSet of the provided elements
* @throws NullPointerException if any elements are null
* @throws IllegalArgumentException if any elements are duplicated
*/
public static <E> OrderedSet<E> of(E e1, E e2, E e3) {
return new OrderedSetImpl<>(Set.of(e1, e2, e3), List.of(e1, e2, e3));
}

/**
* Returns an OrderedSet with four elements.
*
* @param <E> element type
* @param e1 first element
* @param e2 second element
* @param e3 third element
* @param e4 fourth element
* @return an OrderedSet of the provided elements
* @throws NullPointerException if any elements are null
* @throws IllegalArgumentException if any elements are duplicated
*/
public static <E> OrderedSet<E> of(E e1, E e2, E e3, E e4) {
return new OrderedSetImpl<>(Set.of(e1, e2, e3, e4), List.of(e1, e2, e3, e4));
}

/**
* Returns an OrderedSet with five elements.
*
* @param <E> element type
* @param e1 first element
* @param e2 second element
* @param e3 third element
* @param e4 fourth element
* @param e5 fifth element
* @return an OrderedSet of the provided elements
* @throws NullPointerException if any elements are null
* @throws IllegalArgumentException if any elements are duplicated
*/
public static <E> OrderedSet<E> of(E e1, E e2, E e3, E e4, E e5) {
return new OrderedSetImpl<>(Set.of(e1, e2, e3, e4, e5), List.of(e1, e2, e3, e4, e5));
}

/**
* Returns an OrderedSet of the provided elements.
*
* @param <E> element type
* @param elements elements
* @return an OrderedSet of the provided elements
* @throws c
* @throws IllegalArgumentException if any elements are duplicated
*/
@SafeVarargs
@SuppressWarnings("varargs")
public static <E> OrderedSet<E> of(E... elements) {
return new OrderedSetImpl<>(Set.of(elements), List.of(elements));
}

/**
* Returns an unmodifiable OrderedSet that contains a copy of the provided
* Set. The order will be the same as the iteration order of the set.
* <p>
* If the set is already an unmodifiable OrderedSet it may be returned as
* is.
*
* @param <E> element type
* @param set set to copy
* @return an ordered set copy of the provided set
* @throws NullPointerException if any element is null or the set is null
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public static <E> OrderedSet<E> copyOf(Set<? extends E> set) {
if (set instanceof OrderedSetImpl) {
return (OrderedSet<E>) set;
} else {
return (OrderedSet<E>) OrderedSet.of(set.toArray());
}
}
}
Loading

0 comments on commit f1b5d5e

Please sign in to comment.