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

craterdog.collections.List Maven / Gradle / Ivy

/************************************************************************
 * Copyright (c) Crater Dog Technologies(TM).  All Rights Reserved.     *
 ************************************************************************
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.        *
 *                                                                      *
 * This code is free software; you can redistribute it and/or modify it *
 * under the terms of The MIT License (MIT), as published by the Open   *
 * Source Initiative. (See http://opensource.org/licenses/MIT)          *
 ************************************************************************/
package craterdog.collections;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import craterdog.collections.abstractions.Collection;
import craterdog.collections.abstractions.OpenCollection;
import craterdog.core.Iterator;
import craterdog.core.Manipulator;
import craterdog.collections.abstractions.SortableCollection;
import craterdog.collections.primitives.DynamicArray;
import java.util.Arrays;
import org.slf4j.ext.XLogger;
import org.slf4j.ext.XLoggerFactory;


/**
 * This collection class implements a sortable list which performs very well for both inserts and
 * indexed lookups of its values.  The implementation dynamically scales up and down the size of
 * the underlying data structures as the number of associations changes over time. The indexing
 * is unit based and allows positive indexes starting at the beginning of the collection or
 * negative indexes starting at the end of the collection as follows:
 * 
 *         1             2             3               N
 *    [element 1] . [element 2] . [element 3] ... [element N]
 *        -N          -(N-1)        -(N-2)            -1
 * 
* * @author Derk Norton * @param The type of element managed by the collection. */ public class List extends SortableCollection { static private final XLogger logger = XLoggerFactory.getXLogger(List.class); private final DynamicArray array; /** * This constructor creates a new empty list. */ public List() { logger.entry(); this.array = new DynamicArray<>(); logger.exit(); } /** * This constructor creates a new list using the elements provided in an array. * * @param elements The elements that should be used to seed the list. */ @JsonCreator public List(E[] elements) { logger.entry(elements); int size = elements.length; this.array = new DynamicArray<>(size); this.array.addAll(Arrays.asList(elements)); logger.exit(); } @JsonValue @Override public E[] toArray() { return super.toArray(); } /** * This constructor creates a new list using the elements provided in a collection. * * @param elements The elements that should be used to seed the list. */ public List(Collection elements) { logger.entry(elements); int size = elements.getSize(); this.array = new DynamicArray<>(size); for (E element : elements) { this.array.add(element); } logger.exit(); } /** * This constructor creates a new list using the elements provided in a java collection. * * In general it is confusing to mix java collections with craterdog collections since * the former uses zero based indexing and the latter uses positive and negative ordinal * based indexing. * * @param elements The elements that should be used to seed the list. */ public List(java.util.Collection elements) { logger.entry(elements); this.array = new DynamicArray<>(elements); logger.exit(); } @Override protected > T emptyCopy() { @SuppressWarnings("unchecked") T copy = (T) new List<>(); return copy; } @Override public final int getSize() { logger.entry(); int size = array.size(); logger.exit(size); return size; } @Override public final E getElement(int index) { logger.entry(index); index = normalizedIndex(index); E element = array.get(index - 1); // convert to zero based indexing logger.exit(element); return element; } @Override public final int getIndex(E element) { logger.entry(element); int index = array.indexOf(element) + 1; // convert to ordinal based indexing logger.exit(index); return index; } @Override public final List getElements(int firstIndex, int lastIndex) { logger.entry(firstIndex, lastIndex); firstIndex = normalizedIndex(firstIndex); lastIndex = normalizedIndex(lastIndex); List result = new List<>(); Iterator iterator = createIterator(); iterator.toIndex(firstIndex); int numberOfElements = lastIndex - firstIndex + 1; while (numberOfElements-- > 0) { E element = iterator.getNext(); logger.debug("Including element: {}", element); result.addElement(element); } logger.exit(result); return result; } @Override public final boolean addElement(E element) { logger.entry(element); boolean result = array.add(element); logger.exit(result); return result; } /** * This method inserts the specified element into the collection before the element * associated with the specified index. * * @param element The new element to be inserted into the collection. * @param index The index of the element before which the new element is to be inserted. */ public final void insertElement(E element, int index) { logger.entry(element, index); index = normalizedIndex(index); array.add(index - 1, element); // convert to zero based indexing logger.exit(); } /** * This method inserts the specified elements into the collection before the element * associated with the specified index. The new elements are inserted in the same * order as they appear in the specified list. * * @param elements The new elements to be inserted into the collection. * @param index The index of the element before which the new element is to be inserted. */ public final void insertElements(Iterable elements, int index) { logger.entry(elements, index); index = normalizedIndex(index); Manipulator manipulator = createManipulator(); manipulator.toIndex(index); for (E element : elements) { logger.debug("Inserting element: {}", element); manipulator.insertElement(element); } logger.exit(); } /** * This method replaces an existing element in the collection with a new one. The new * element replaces the existing element at the specified index. * * @param element The new element that will replace the existing one. * @param index The index of the existing element. * * @return The element that was at the specified index. */ public final E replaceElement(E element, int index) { logger.entry(element, index); index = normalizedIndex(index); E result = array.set(index - 1, element); // convert to zero based indexing logger.exit(result); return result; } /** * This method removes from the collection the element associated with the specified * index. * * @param index The index of the element to be removed. * @return The element at the specified index. */ public final E removeElement(int index) { logger.entry(index); index = normalizedIndex(index); E result = array.remove(index - 1); // convert to zero based indexing logger.exit(result); return result; } @Override public final boolean removeElement(E element) { logger.entry(element); boolean result = array.remove(element); logger.exit(result); return result; } /** * This method removes from the collection the elements associated with the specified * index range. * * @param firstIndex The index of the first element to be removed. * @param lastIndex The index of the last element to be removed. * @return The list of the elements that were removed from the collection. */ public final List removeElements(int firstIndex, int lastIndex) { logger.entry(firstIndex, lastIndex); firstIndex = normalizedIndex(firstIndex); lastIndex = normalizedIndex(lastIndex); if (lastIndex < firstIndex) { // handle the case where the indexes are backwards int swap = firstIndex; firstIndex = lastIndex; lastIndex = swap; } List result = new List<>(array.remove(firstIndex - 1, lastIndex)); // convert to zero based indexing logger.exit(result); return result; } @Override public final void removeAll() { logger.entry(); array.clear(); logger.exit(); } @Override public Iterator createIterator() { logger.entry(); Iterator iterator = new ListManipulator(); logger.exit(iterator); return iterator; } @Override public Manipulator createManipulator() { logger.entry(); Manipulator manipulator = new ListManipulator(); logger.exit(manipulator); return manipulator; } /** * This function returns a new list that contains the all the elements from * both the specified lists. * * @param The type of element contained in the lists. * @param list1 The first list whose elements are to be added. * @param list2 The second list whose elements are to be added. * @return The resulting list. */ static public List concatenation(List list1, List list2) { logger.entry(list1, list2); List result = new List<>(list1); result.addElements(list2); logger.exit(result); return result; } /* * This manipulator class implements both the Iterator abstraction * and the Manipulator abstraction so it can be used as either depending * on how it is returned from the list. It utilizes the list iterators for the * underlying list implementations. Like most iterators, it should be used to access * a list exclusively without any other requests, especially requests that change the * length of the list, being made directly on the same list. None of the manipulator * methods will cause the implementation of the list to be switched to a different * implementation. */ private class ListManipulator extends Manipulator { private java.util.ListIterator iterator = array.iterator(); @Override public void toStart() { logger.entry(); iterator = array.iterator(); logger.exit(); } @Override public void toIndex(int index) { logger.entry(index); index = normalizedIndex(index); iterator = array.listIterator(index - 1); // convert to zero based indexing logger.exit(); } @Override public void toEnd() { logger.entry(); iterator = array.listIterator(array.size()); // convert to zero based indexing logger.exit(); } @Override public boolean hasPrevious() { logger.entry(); boolean result = iterator.nextIndex() > 0; logger.exit(result); return result; } @Override public boolean hasNext() { logger.entry(); boolean result = iterator.nextIndex() < array.size(); logger.exit(result); return result; } @Override public E getNext() { logger.entry(); if (!hasNext()) { IllegalStateException exception = new IllegalStateException("The iterator is at the end of the list."); throw logger.throwing(exception); } E result = iterator.next(); logger.exit(result); return result; } @Override public E getPrevious() { logger.entry(); if (!hasPrevious()) { IllegalStateException exception = new IllegalStateException("The iterator is at the beginning of the list."); throw logger.throwing(exception); } E result = iterator.previous(); logger.exit(result); return result; } @Override public void insertElement(E element) { logger.entry(element); iterator.add(element); logger.exit(); } @Override public E removeNext() { logger.entry(); if (!hasNext()) { IllegalStateException exception = new IllegalStateException("The iterator is at the end of the list."); throw logger.throwing(exception); } E result = iterator.next(); iterator.remove(); logger.exit(result); return result; } @Override public E removePrevious() { logger.entry(); if (!hasPrevious()) { IllegalStateException exception = new IllegalStateException("The iterator is at the beginning of the list."); throw logger.throwing(exception); } E result = iterator.previous(); iterator.remove(); logger.exit(result); return result; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy