为了账号安全,请及时绑定邮箱和手机立即绑定

如何在java中存储一组唯一的整数数组

如何在java中存储一组唯一的整数数组

千巷猫影 2024-01-05 09:59:32
我正在尝试在 java 中存储唯一整数数组的列表。我无法使用哈希集,因为 .equals 方法不会将具有相同值但不同引用的 int[] 等同。
查看完整描述

3 回答

?
跃然一笑

TA贡献1826条经验 获得超6个赞

一种选择是使用List<Integer>而不是int[]作为 的元素Set,这将允许您使用任何Set实现。

如果必须使用数组,可以将它们存储在 a 中TreeSet<int[]>,并将自定义Comparator<int[]>传递给TreeSet构造函数。这应该可行,因为TreeSet不使用equals()andhashCode()来确定两个元素是否相同。


查看完整回答
反对 回复 2024-01-05
?
摇曳的蔷薇

TA贡献1793条经验 获得超6个赞

我认为以下代码片段将是您的解决方案。如果我答对了


List<Integer> numberList = new ArrayList<Integer>();

int[] myInts = {1, 1, 2, 3, 3, 3, 3, 4};

for (int i : myInts) {

  if (!numberList.contains(i)) {

     numberList.add(i);

   }

}


查看完整回答
反对 回复 2024-01-05
?
一只斗牛犬

TA贡献1784条经验 获得超2个赞

您可以将int[]数组包装在一个特殊的容器中,该容器会覆盖equals和hashCode:


public class IntArrayHolder {

    private final int[] array;


    public IntArrayHolder(int[] array) {

        this.array = array;

    }


    public int[] getArray() {

        return array;

    }


    @Override

    public boolean equals(Object object) {

        if (this == object) return true;

        if (!(object instanceof IntArrayHolder)) return false;

        IntArrayHolder that = (IntArrayHolder) object;

        return Arrays.equals(array, that.array);

    }


    @Override

    public int hashCode() {

        return Arrays.hashCode(array);

    }

}

并使用Set<IntArrayHolder>而不是Set<int[]>:


Set<IntArrayHolder> set = new HashSet<>();

set.add(new IntArrayHolder(new int[]{0}));

set.add(new IntArrayHolder(new int[]{0}));

set.add(new IntArrayHolder(new int[]{1}));

set.forEach(elm -> System.out.println(Arrays.toString(elm.getArray()))); // prints [1][0]

您还可以将包装和解包装封装在特殊的泛型类中,并以这种方式使用它们:


Set<int[]> set = new MappedSet<>(new HashSet<>(), Mapper.from(

        IntArrayHolder::getArray,

        IntArrayHolder::new

));

set.add(new int[]{0});

set.add(new int[]{0});

set.add(new int[]{1});

set.forEach(elm -> System.out.println(Arrays.toString(elm))); // prints [1][0]

这里是Mapper、MappedSet、MappedCollection、MappedIterable和MappedIterator:MappedArray

/**

 * <h1>Mapper</h1>

 * Represents a two way function which can be used for adapting

 * {@code Type<A>} to {@code Type<B>} where {@code Type} is invariant

 * generic type.

 *

 * <h2>Invertibility</h2>

 * <p>

 * If this mapper isn't bounded result of performing {@code out(in(x))} should

 * be similar to {@code x}, no guarantees are made about their equality. The same goes

 * with {@code in(out(x))}.

 *

 * <h2>Nullability</h2>

 * <p>

 * A mapper always converts {@code null} to {@code null} and non-null references to non-null

 * references. {@code null} can be passed to {@link #out(A)} and {@link #in(B)} methods, but

 * should never be passed to {@link #doOut(A)} and {@link #doIn(B)}.

 *

 * <h2>Bounded wildcards</h2>

 * <p>

 * Bounded wildcards should never be used on {@link A} type parameter, because mapper with bounded

 * {@link A} can't be accepted by any adapter and is completely useless.

 *

 * <p>Using of bounded wildcard on {@link B} type parameter indicates that mapper can perform

 * operations in only one way see {@link #outMapper(Function)} and {@link #inMapper(Function)}.

 *

 * <h2>Unchecked functionality</h2>

 * A mapper provides unchecked functionality for not generified methods via {@link #uncheckedOut(Object)},

 * {@link #uncheckedIn(Object)} and {@link #unchecked()} methods.

 * <p>Restricting unchecked functionality can be done by using {@link #restrictAClass(Class)}

 * and {@link #restrictBClass(Class)} methods.

 *

 * <h2>Instantiation</h2>

 * The following factory methods can be used for mapper instantiation:

 * <ul>

 *     <li>{@link #from(Function, Function)} - two ways mapper</li>

 *     <li>{@link #outMapper(Function)} - only-out mapper</li>

 *     <li>{@link #inMapper(Function)} - only-in mapper</li>

 * </ul>

 * <p>This interface can also be implemented from outside.

 *

 * @param <A> type parameter of adapted generic instance

 * @param <B> type parameter of generic adapter

 */

public interface Mapper<A, B> extends Function<A, B> {

    /**

     * Adapts return value of adapted instance method to adapter type.

     *

     * @param a result of calling adapted instance method

     * @return result which should be return from adapter

     * @implNote this method isn't supposed to be overridden, instead {@link #doOut(A)}

     * method should be implemented for defining mapper behaviour

     */

    @Contract("null -> null; !null -> !null")

    @Final

    default @Nullable B out(@Nullable A a) {

        return a == null ? null : doOut(a);

    }


    /**

     * Adapts input argument of adapter method to adapted instance type.

     *

     * @param b argument passed to adapter method

     * @return argument which should be passed to adapted instance

     * @implNote this method isn't supposed to be overridden, instead {@link #doIn(B)}

     * method should be implemented for defining mapper behaviour

     */

    @Contract("null -> null; !null -> !null")

    @Final

    default @Nullable A in(@Nullable B b) {

        return b == null ? null : doIn(b);

    }


    /**

     * Adapts return value of not generified adapted instance method to adapter type,

     * uses unchecked cast.

     *

     * @param a result of calling adapted instance method, is to have {@link A} type

     * @return result which should be return from adapter

     * @see #out(A)

     */

    @SuppressWarnings("unchecked") // unchecked is indicated in the method name

    @Contract("null -> null; !null -> !null")

    @Final

    default @Nullable B uncheckedOut(@Nullable Object a) {

        return out((A) a);

    }


    /**

     * Adapts input argument of not generified adapter method to adapted instance type,

     * uses unchecked cast.

     *

     * @param b argument passed to adapter method, is to have {@link B} type

     * @return argument which should be passed to adapted instance

     * @see #in(B)

     */

    @SuppressWarnings("unchecked") // unchecked is indicated in the method name

    @Contract("null -> null; !null -> !null")

    @Final

    default @Nullable A uncheckedIn(@Nullable Object b) {

        return in((B) b);

    }


    /**

     * Performs adapting of {@link A} to {@link B}.

     *

     * @param a input argument, mustn't be {@code null}

     * @return adaptation result, mustn't be {@code null}. If adaptation has failed {@link IllegalArgumentException}

     * should be thrown or null-object should be returned.

     * @apiNote this method isn't supposed to be called, instead {@link #out(A)} method should be used

     * @implNote this method is supposed to be implemented for defining {@link #out(A)} method behaviour

     * @see #out(A)

     */

    @NotNull B doOut(@NotNull A a);


    /**

     * Performs adapting of {@link B} to {@link A}.

     *

     * @param b input argument, mustn't be {@code null}

     * @return adaptation result, mustn't be {@code null}. If adaptation has failed {@link IllegalArgumentException}

     * should be thrown or null-object should be returned.

     * @apiNote this method isn't supposed to be called, instead {@link #in(B)} method should be used

     * @implNote this method is supposed to be implemented for defining {@link #in(B)} method behaviour

     * @see #in(B)

     */

    @NotNull A doIn(@NotNull B b);


    /**

     * Non-null analog of {@link #out(A)}.

     *

     * @param a input argument

     * @return mapping result

     * @apiNote {@code mapper::apply} shouldn't be used, instead mapper instance itself

     * should be used as a {@code Function<A, B>}

     */

    @Override

    default @NotNull B apply(@NotNull A a) {

        return out(a);

    }


    /**

     * Non-null analog of {@link #in(B)}.

     *

     * @param b input argument

     * @return mapping result

     * @apiNote {@code mapper::undo} shouldn't be used, instead {@link #reverse()}

     * should be used as a {@code Function<B, A>}

     */

    default @NotNull A undo(@NotNull B b) { return in(b); }


    /**

     * Returns reverse view of this mapper.

     * <p>Some mappers may perform reverse view caching, so it's likely that

     * {@code mapper.reverse() == mapper.reverse()} and {@code mapper.reverse().reverse() == mapper}

     * will be true.

     *

     * @return reverse view of this mapper

     */

    default Mapper<B, A> reverse() {

        return new Mapper<B, A>() {

            @Override

            public @NotNull A doOut(@NotNull B b) {

                return Mapper.this.doIn(b);

            }


            @Override

            public @NotNull B doIn(@NotNull A a) {

                return Mapper.this.doOut(a);

            }


            @Override

            public Mapper<A, B> reverse() {

                return Mapper.this;

            }

        };

    }


    /**

     * Returns this mapper after unchecked casting to required type.

     * <p>Should be used carefully: sometimes {@link #reverse()}{@code .unchecked()} is required instead

     * of {@code unchecked()}.

     *

     * @param <A2> {@link A} type parameter of returned mapper

     * @return this instance

     * @see #uncheckedIn(Object)

     * @see #uncheckedOut(Object)

     */

    @SuppressWarnings("unchecked") // unchecked is indicated in the method name

    @Contract(value = "-> this", pure = true)

    default <A2> Mapper<A2, B> unchecked() {

        return (Mapper<A2, B>) this;

    }


    @SuppressWarnings("unchecked") // unchecked is indicated in the method name

    default <A2, B2> Mapper<A2, B2> doubleUnchecked() {

        return (Mapper<A2, B2>) this;

    }


    /**

     * Creates a composed mapper from {@link V} to {@link B} which uses {@code before}

     * mapper and this mapper in order required by operations.

     *

     * @param <V>    the first type parameter of {@code before} mapper, and of the

     *               composed mapper

     * @param before the additional mapper

     * @return a composed mapper

     * @see #andThenMapper(Mapper)

     * @see #compose(Function)

     */

    @Contract(value = "_ -> new", pure = true)

    default <V> Mapper<V, B> composeMapper(Mapper<V, A> before) {

        return before.andThenMapper(this);

    }


    /**

     * Creates a composed mapper from {@link A} to {@link C} which uses this

     * mapper and {@code after} mapper in order required by operations.

     *

     * @param <C>   the second type parameter of {@code after} mapper, and of the

     *              composed mapper

     * @param after the additional mapper

     * @return a composed mapper

     * @see #composeMapper(Mapper)

     * @see #andThen(Function)

     */

    @Contract(value = "_ -> new", pure = true)

    default <C> Mapper<A, C> andThenMapper(Mapper<B, C> after) {

        return from(a -> after.out(out(a)), c -> in(after.in(c)));

    }


    /**

     * Creates mapper which restricts {@link A} class, so type of {@link #out(A)} operation parameter

     * is checked before performing operation.

     * <p>If parameter isn't an {@code instanceof clazz} {@link #uncheckedMap(Object)} is used.

     *

     * @param clazz {@link A} class

     * @return mapper which restricts {@link A} class

     * @see #restrictBClass(Class)

     */

    @Contract(value = "_ -> new", pure = true)

    default Mapper<A, B> restrictAClass(Class<A> clazz) {

        return from(a -> clazz.isAssignableFrom(a.getClass()) ? doOut(a) : uncheckedMap(a), this::doIn);

    }


    /**

     * Creates mapper which restricts {@link B} class, so type of {@link #in(B)} operation parameter

     * is checked before performing operation.

     * <p>If parameter isn't an {@code instanceof clazz} {@link #uncheckedMap(Object)} is used.

     *

     * @param clazz {@link B} class

     * @return mapper which restricts {@link B} class

     * @see #restrictAClass(Class)

     */

    @Contract(value = "_ -> new", pure = true)

    default Mapper<A, B> restrictBClass(Class<B> clazz) {

        return from(this::doOut, b -> clazz.isAssignableFrom(b.getClass()) ? doIn(b) : uncheckedMap(b));

    }


    /**

     * Creates mapper from given functions.

     *

     * @param out function for performing {@link #doOut(A)} method

     * @param in  function for performing {@link #doIn(B)} method

     * @param <A> returned mapper first type parameter

     * @param <B> returned mapper second type parameter

     * @return created mapper

     */

    @Contract(value = "_, _ -> new", pure = true)

    static <A, B> Mapper<A, B> from(Function<? super A, ? extends B> out, Function<? super B, ? extends A> in) {

        return new Mapper<A, B>() {

            private @Nullable Mapper<B, A> reverse = null;


            @Override

            public @NotNull B doOut(@NotNull A a) {

                return out.apply(a);

            }


            @Override

            public @NotNull A doIn(@NotNull B b) {

                return in.apply(b);

            }


            @Override

            public Mapper<B, A> reverse() {

                return (reverse == null) ? (reverse = Mapper.super.reverse()) : reverse;

            }

        };

    }


    /**

     * Creates mapper that can only normally perform {@link #out(A)} operation.

     *

     * <p>The returned mapper is bounded so {@link #in(B)} operation without using <i>unchecked functionality</i>

     * can only be called with {@code null} argument, according to the contract this will lead to

     * returning of {@code null}.

     *

     * @param out function for performing {@link #doOut(A)} method

     * @param <A> returned mapper first type parameter

     * @param <B> returned mapper second type parameter

     * @return mapper that only provides {@link #out(A)} operation

     */

    @Contract(value = "_ -> new", pure = true)

    static <A, B> Mapper<A, ? extends B> outMapper(Function<? super A, ? extends B> out) {

        return from(out, Mapper::uncheckedMap);

    }


    /**

     * Creates mapper that can only normally perform {@link #in(B)} operation.

     *

     * <p>The returned mapper is bounded so {@link #out(A)} result can be used only as {@link Object}.

     * <p>Returned mapper guarantees that {@code out(x) == x} will always be {@code true}.

     *

     * @param in  function for performing {@link #doIn(B)} method

     * @param <A> returned mapper first type parameter

     * @param <B> returned mapper second type parameter

     * @return mapper that only provides {@link #in(B)} operation

     */

    @Contract(value = "_ -> new", pure = true)

    static <A, B> Mapper<A, ? super B> inMapper(Function<? super B, ? extends A> in) {

        return from(Mapper::uncheckedMap, in);

    }


    /**

     * Creates mapper that maps any object to itself.

     *

     * @param <T> returned mapper type parameter

     * @return created mapper

     */

    @Contract(value = "-> new", pure = true)

    static <T> Mapper<T, T> identity() {

        return from(Function.identity(), Function.identity());

    }


    /**

     * Performs unchecked cast of input to required type,

     * this method may also do some logging.

     *

     * <p>This method is supposed to be used when impossible to call {@code Function<? extends A, B>} or

     * returning {@link Object} {@code Function<A, ? super B>} is needed.

     *

     * <p>In some cases it can also be called when {@code a} appeared to be not an {@code instanceof Class<A>}.

     *

     * @param a   input argument

     * @param <A> input argument type

     * @param <B> required type

     * @return result of unchecked cast

     * @deprecated unchecked cast

     */

    @SuppressWarnings({"Contract", "unchecked"}) // unchecked is indicated in the method name

    @Contract("_ -> param1")

    @Deprecated

    @WarnOnUse(exceptClasses = Mapper.class)

    static <A, B> B uncheckedMap(A a) {

        return (B) a;

    }

}


public class MappedSet<E, E2> extends MappedCollection<E, E2> implements Set<E2> {

    public MappedSet(Set<E> set, Mapper<E, E2> mapper) {

        super(set, mapper);

    }


    public static <E, E2> Set<E2> map(Set<E> inst, Mapper<E, E2> mapper) {

        return new MappedSet<>(inst, mapper);

    }


    public static <E, E2> Set<? extends E2> mapOut(Set<? extends E> inst, Function<? super E, ? extends E2> mapper) {

        return map(inst, Mapper.outMapper(mapper));

    }


    public static <E, E2> Set<? super E2> mapIn(Set<? super E> inst, Function<? super E2, ? extends E> mapper) {

        return map(inst, Mapper.inMapper(mapper));

    }

}


public class MappedCollection<E, E2> extends MappedIterable<E, E2> implements Collection<E2> {

    private final Collection<E> collection;

    private final Mapper<E, E2> mapper;


    public MappedCollection(Collection<E> collection, Mapper<E, E2> mapper) {

        super(collection, mapper);

        this.collection = collection;

        this.mapper = mapper;

    }


    public static <E, E2> Collection<E2> map(Collection<E> inst, Mapper<E, E2> mapper) {

        return new MappedCollection<>(inst, mapper);

    }


    public static <E, E2> Collection<? extends E2> mapOut(Collection<? extends E> inst, Function<? super E, ? extends E2> mapper) {

        return map(inst, Mapper.outMapper(mapper));

    }


    public static <E, E2> Collection<? super E2> mapIn(Collection<? super E> inst, Function<? super E2, ? extends E> mapper) {

        return map(inst, Mapper.inMapper(mapper));

    }


    @Override

    public int size() {

        return collection.size();

    }


    @Override

    public boolean isEmpty() {

        return collection.isEmpty();

    }


    @Override

    public boolean contains(Object o) {

        return collection.contains(mapper.uncheckedIn(o));

    }


    @Override

    public @NotNull Object[] toArray() {

        return MappedArray.map(collection.toArray(), mapper.unchecked());

    }


    @Override

    public @NotNull <T> T[] toArray(@NotNull T[] a) {

        return MappedArray.map(collection.toArray(), ContainersUtils.getComponentType(a), mapper.doubleUnchecked());

    }


    @Contract(mutates = "this")

    @Override

    public boolean add(@NotNull E2 e2) {

        return collection.add(mapper.in(e2));

    }


    @Contract(mutates = "this")

    @Override

    public boolean remove(Object o) {

        return collection.remove(mapper.uncheckedIn(o));

    }


    @Override

    public boolean containsAll(@NotNull Collection<?> c) {

        return collection.containsAll(map(c, mapper.reverse().unchecked()));

    }


    @Contract(mutates = "this")

    @Override

    public boolean addAll(@NotNull Collection<? extends E2> c) {

        return collection.addAll(mapOut(c, mapper.reverse()));

    }


    @Contract(mutates = "this")

    @Override

    public boolean removeAll(@NotNull Collection<?> c) {

        return collection.removeAll(map(c, mapper.reverse().unchecked()));

    }


    @Contract(mutates = "this")

    @Override

    public boolean retainAll(@NotNull Collection<?> c) {

        return collection.retainAll(map(c, mapper.reverse().unchecked()));

    }


    @Contract(mutates = "this")

    @Override

    public void clear() {

        collection.clear();

    }

}


@RequiredArgsConstructor

public class MappedIterable<E, E2> implements Iterable<E2> {

    private final @NotNull Iterable<E> iterable;

    private final @NotNull Function<? super E, ? extends E2> mapper;


    public static <E, E2> Iterator<E2> map(Iterator<E> inst, Function<? super E, ? extends E2> mapper) {

        return new MappedIterator<>(inst, mapper);

    }


    @Override

    public @NotNull Iterator<E2> iterator() {

        return MappedIterator.map(iterable.iterator(), mapper);

    }

}


@RequiredArgsConstructor

public class MappedIterator<E, E2> implements Iterator<E2> {

    private final @NotNull Iterator<E> iterator;

    private final @NotNull Function<? super E, ? extends E2> mapper;


    public static <E, E2> Iterator<E2> map(Iterator<E> inst, Function<? super E, ? extends E2> mapper) {

        return new MappedIterator<>(inst, mapper);

    }


    @Contract(pure = true)

    @Override

    public boolean hasNext() {

        return iterator.hasNext();

    }


    @Override

    public E2 next() {

        return mapper.apply(iterator.next());

    }

}


@UtilityClass

public class MappedArray {

    public static <T> Object[] map(T[] inst, Function<? super T, ?> mapper) {

        return Stream.of(inst).map(mapper).toArray();

    }


    public static <T, T2> T2[] map(T[] inst, Class<T2> clazz, Function<? super T, ? extends T2> mapper) {

        return Stream.of(inst).map(mapper).toArray(i -> ContainersUtils.createArray(clazz, i));

    }

}


查看完整回答
反对 回复 2024-01-05
  • 3 回答
  • 0 关注
  • 106 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信