All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.vavr.collection.JavaConverters Maven / Gradle / Ivy

There is a newer version: 1.0.0-alpha-4
Show newest version
/*  __    __  __  __    __  ___
 * \  \  /  /    \  \  /  /  __/
 *  \  \/  /  /\  \  \/  /  /
 *   \____/__/  \__\____/__/
 *
 * Copyright 2014-2019 Vavr, http://vavr.io
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.vavr.collection;

import java.io.Serializable;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Supplier;

/**
 * THIS CLASS IS INTENDED TO BE USED INTERNALLY ONLY!
 * 

* This helper class provides methods that return views on Java collections. * The view creation and back conversion take O(1). * * @author Daniel Dietrich */ class JavaConverters { private JavaConverters() { } @GwtIncompatible static > ListView asJava(C seq, ChangePolicy changePolicy) { return new ListView<>(seq, changePolicy.isMutable()); } enum ChangePolicy { IMMUTABLE, MUTABLE; boolean isMutable() { return this == MUTABLE; } } // -- private view implementations /** * Encapsulates the access to delegate and performs mutability checks. * * @param The Vavr collection type */ private static abstract class HasDelegate> implements Serializable { private static final long serialVersionUID = 1L; private C delegate; private final boolean mutable; HasDelegate(C delegate, boolean mutable) { this.delegate = delegate; this.mutable = mutable; } protected boolean isMutable() { return mutable; } C getDelegate() { return delegate; } protected boolean setDelegateAndCheckChanged(Supplier delegate) { ensureMutable(); final C previousDelegate = this.delegate; final C newDelegate = delegate.get(); final boolean changed = newDelegate.size() != previousDelegate.size(); if (changed) { this.delegate = newDelegate; } return changed; } protected void setDelegate(Supplier newDelegate) { ensureMutable(); this.delegate = newDelegate.get(); } protected void ensureMutable() { if (!mutable) { throw new UnsupportedOperationException(); } } } @GwtIncompatible("reflection is not supported") static class ListView> extends HasDelegate implements java.util.List { private static final long serialVersionUID = 1L; ListView(C delegate, boolean mutable) { super(delegate, mutable); } @SuppressWarnings("unchecked") @Override public boolean add(T element) { setDelegate(() -> (C) getDelegate().append(element)); return true; } @SuppressWarnings("unchecked") @Override public void add(int index, T element) { setDelegate(() -> (C) getDelegate().insert(index, element)); } @SuppressWarnings("unchecked") @Override public boolean addAll(Collection collection) { Objects.requireNonNull(collection, "collection is null"); return setDelegateAndCheckChanged(() -> (C) getDelegate().appendAll(collection)); } @SuppressWarnings("unchecked") @Override public boolean addAll(int index, Collection collection) { Objects.requireNonNull(collection, "collection is null"); return setDelegateAndCheckChanged(() -> (C) getDelegate().insertAll(index, collection)); } @SuppressWarnings("unchecked") @Override public void clear() { // DEV-NOTE: acts like Java: works for empty immutable collections if (isEmpty()) { return; } setDelegate(() -> (C) getDelegate().take(0)); } @Override public boolean contains(Object obj) { @SuppressWarnings("unchecked") final T that = (T) obj; return getDelegate().contains(that); } @Override public boolean containsAll(Collection collection) { Objects.requireNonNull(collection, "collection is null"); @SuppressWarnings("unchecked") final Collection that = (Collection) collection; return getDelegate().containsAll(that); } @Override public T get(int index) { return getDelegate().get(index); } @Override public int indexOf(Object obj) { @SuppressWarnings("unchecked") final T that = (T) obj; return getDelegate().indexOf(that); } @Override public boolean isEmpty() { return getDelegate().isEmpty(); } @Override public java.util.Iterator iterator() { return new Iterator<>(this); } @Override public int lastIndexOf(Object obj) { @SuppressWarnings("unchecked") final T that = (T) obj; return getDelegate().lastIndexOf(that); } @Override public java.util.ListIterator listIterator() { return new ListIterator<>(this, 0); } @Override public java.util.ListIterator listIterator(int index) { return new ListIterator<>(this, index); } @SuppressWarnings("unchecked") @Override public T remove(int index) { return setDelegateAndGetPreviousElement(index, () -> (C) getDelegate().removeAt(index)); } @SuppressWarnings("unchecked") @Override public boolean remove(Object obj) { final T that = (T) obj; return setDelegateAndCheckChanged(() -> (C) getDelegate().remove(that)); } @SuppressWarnings("unchecked") @Override public boolean removeAll(Collection collection) { Objects.requireNonNull(collection, "collection is null"); @SuppressWarnings("unchecked") final Collection that = (Collection) collection; return setDelegateAndCheckChanged(() -> (C) getDelegate().removeAll(that)); } @SuppressWarnings("unchecked") @Override public boolean retainAll(Collection collection) { Objects.requireNonNull(collection, "collection is null"); @SuppressWarnings("unchecked") final Collection that = (Collection) collection; return setDelegateAndCheckChanged(() -> (C) getDelegate().retainAll(that)); } @SuppressWarnings("unchecked") @Override public T set(int index, T element) { return setDelegateAndGetPreviousElement(index, () -> (C) getDelegate().update(index, element)); } @Override public int size() { return getDelegate().size(); } @SuppressWarnings("unchecked") @Override public void sort(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); if (isEmpty()) { return; } setDelegate(() -> (C) getDelegate().sorted(comparator)); } @Override public java.util.List subList(int fromIndex, int toIndex) { return new ListView<>(getDelegate().subSequence(fromIndex, toIndex), isMutable()); } @Override public Object[] toArray() { return getDelegate().toJavaArray(); } @SuppressWarnings("unchecked") @Override public U[] toArray(U[] array) { Objects.requireNonNull(array, "array is null"); final U[] target; final C delegate = getDelegate(); final int length = delegate.length(); if (array.length < length) { final Class newType = array.getClass(); target = (newType == Object[].class) ? (U[]) new Object[length] : (U[]) java.lang.reflect.Array.newInstance(newType.getComponentType(), length); } else { if (array.length > length) { array[length] = null; } target = array; } final java.util.Iterator iter = delegate.iterator(); for (int i = 0; i < length; i++) { target[i] = (U) iter.next(); } return target; } // -- Object.* @Override public boolean equals(Object o) { return o == this || o instanceof java.util.List && Collections.areEqual(getDelegate(), (java.util.List) o); } @Override public int hashCode() { // DEV-NOTE: Ensures that hashCode calculation is stable, regardless of delegate.hashCode() return Collections.hashOrdered(getDelegate()); } @Override public String toString() { return getDelegate().mkString("[", ", ", "]"); } // -- private helpers private T setDelegateAndGetPreviousElement(int index, Supplier delegate) { ensureMutable(); final T previousElement = getDelegate().get(index); setDelegate(delegate); return previousElement; } // DEV-NOTE: Iterator is intentionally not Serializable private static class Iterator> implements java.util.Iterator { ListView list; int expectedSize; int nextIndex = 0; int lastIndex = -1; Iterator(ListView list) { this.list = list; expectedSize = list.size(); } @Override public boolean hasNext() { return nextIndex != list.size(); } @Override public T next() { checkForComodification(); if (nextIndex >= list.size()) { throw new NoSuchElementException(); } try { return list.get(lastIndex = nextIndex++); } catch (IndexOutOfBoundsException x) { throw new ConcurrentModificationException(); } } @Override public void remove() { list.ensureMutable(); if (lastIndex < 0) { throw new IllegalStateException(); } checkForComodification(); try { list.remove(nextIndex = lastIndex); lastIndex = -1; expectedSize = list.size(); } catch (IndexOutOfBoundsException x) { throw new ConcurrentModificationException(); } } @Override public void forEachRemaining(Consumer consumer) { Objects.requireNonNull(consumer, "consumer is null"); checkForComodification(); if (nextIndex >= list.size()) { return; } int index = nextIndex; // DEV-NOTE: intentionally not using hasNext() and next() in order not to modify internal state while (expectedSize == list.size() && index < expectedSize) { consumer.accept(list.get(index++)); } nextIndex = index; lastIndex = index - 1; checkForComodification(); } final void checkForComodification() { if (expectedSize != list.size()) { throw new ConcurrentModificationException(); } } } // DEV-NOTE: ListIterator is intentionally not Serializable private static class ListIterator> extends ListView.Iterator implements java.util.ListIterator { ListIterator(ListView list, int index) { super(list); if (index < 0 || index > list.size()) { throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + list.size()); } this.nextIndex = index; } @Override public boolean hasPrevious() { return nextIndex != 0; } @Override public int nextIndex() { return nextIndex; } @Override public int previousIndex() { return nextIndex - 1; } @Override public T previous() { checkForComodification(); final int index = nextIndex - 1; if (index < 0) { throw new NoSuchElementException(); } if (index >= list.size()) { throw new ConcurrentModificationException(); } try { final T element = list.get(index); // DEV-NOTE: intentionally updating indices _after_ reading the element. This makes a difference in case of a concurrent modification. lastIndex = nextIndex = index; return element; } catch (IndexOutOfBoundsException x) { throw new ConcurrentModificationException(); } } @Override public void set(T element) { list.ensureMutable(); if (lastIndex < 0) { throw new IllegalStateException(); } checkForComodification(); try { list.set(lastIndex, element); } catch (IndexOutOfBoundsException x) { throw new ConcurrentModificationException(); } } @Override public void add(T element) { list.ensureMutable(); checkForComodification(); try { final int index = nextIndex; list.add(index, element); // DEV-NOTE: intentionally increasing nextIndex _after_ adding the element. This makes a difference in case of a concurrent modification. nextIndex = index + 1; lastIndex = -1; expectedSize = list.size(); } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy