So my program has a need of a type of circular ArrayList.
Only circular thing about it has to be the get(int index) method, this is the original:
/**
* Returns the element at the specified position in this list.
*
* #param index index of the element to return
* #return the element at the specified position in this list
* #throws IndexOutOfBoundsException {#inheritDoc}
*/
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
If index is -1 it should get the element with index ArrayList.size()-1 and if index is ArrayList.size(), it should get the element with index 0.
Simplest way of achieveing this which came to my mind is simply extending ArrayList from the java.util package and just overriding the get(int index) so it does not throw IndexOutOfBoundsException for the two indexes above, but change them to what I want. It would throw IndexOutOfBoundsException for any other index that is out of bounds.
However, since elementData(index) access a
private transient Object[] elementData;
I cannot make it work, because my class doesn't see it since it's private.
Also, I don't want to use any external libraries for this, simply because I think there are none that suit my needs, since I don't want a real circularArray, but only a part of it's functionality, rest of it being of the regular ArrayList.
So I have two questions:
How can I make this work? Is there a way to do it without copying the whole ArrayList class along with AbstractCollection, Collection and Iterable into my program? That seems like bad design even to me.
If I can somehow make it work, is there anything else I should watch for? If I make the changes described above, would that change the behaviour of the class only the way I want it to, or could there be any other undesired behaviour changes?
EDIT:
Thanks for the answer, here's what I've done:
import java.util.ArrayList;
public class CircularArrayList<E> extends ArrayList<E>
{
private static final long serialVersionUID = 1L;
public E get(int index)
{
if (index == -1)
{
index = size()-1;
}
else if (index == size())
{
index = 0;
}
return super.get(index);
}
}
It will wrap around the ArrayList, but only by one. I want it to throw an exception if I try to access any other element but the first and the last with anything except their regular ArrayList indexes.
You can extend the ArrayList class to change the functionality of the get method, without the need to access the elementData field:
public class CircularList<E> extends ArrayList<E> {
#Override
public E get(int index) {
return super.get(index % size());
}
}
The super.get method will still perform the range checks (but those will never fail).
You should be aware that doing this can give the ArrayList unstable indices. If the size of the list changes, then all indices outside of the normal range will change. For instance, if you have a list ['a','b','c','d','e'], then get(7) will return c. If you then do add('f'), then get(7) will suddenly return b, because get will now be working modulo 6 instead of modulo 5.
Can't you derive from ArrayList and override the the get(int index) method along those lines:
#Override
public E get(int index)
{
if(index < 0)
index = index + size();
return super.get(index);
}
What am I missing?
Note that this implementation would not fold arbitrary indices into your valid index range but only allow you to properly address your list from both the left and right sides (with positive and negative indices respectively, a bit like in Python).
What you described is basically getting the modulus of the index you want, and accessing that element in a list.
You could do the following with composition over inheritance:
Create a wrapper class for the interface List<T>, let's call it ListWrapper now
add a constructor accepting instance of List
let the List instance be protected, and name it to wrapped
Extend the wrapper class
Why do all this crap? This is implementation agnostic. One day, you might want to use this convenience on another implementation. Then you'll have to duplicate code, and hell begins. If you need a 3rd implementation too, and then add just one tiny bit of new functionality, you are doomed.
With a wrapper class in between:
you can have all classes implementing the List interface to have your own functinality
you'll be able to change the wrapper class in one place
you'll be able to add new functionality in one place.
Remember, we are writing programs that will have to be maintainable!
Wrapper class
public abstract class ListWrapper<T> implements List<T> {
protected final List<T> wrapped;
public ListWrapper(List<T> wrapped) {
this.wrapped = wrapped;
}
public T get(int index) {
return wrapped.get(index);
}
//omitting the other wrapper methods, for sake of brevity.
//Note: you still have to add them.
// Eclipse: Source menu, Generate Delegate methods does the trick nicely
}
Now the real new class
public class ModList<T> extends ListWrapper<T> {
public ModList(List<T> list) {
super(list);
}
#Override
public T get(int index) {
int listSize = wrapped.size();
int indexToGet = index % listSize;
//this might happen to be negative
indexToGet = (indexToGet < 0) ? indexToGet+listSize : indexToGet;
return wrapped.get(indexToGet);
}
}
BEWARE
this however is not safe for multithreaded environments!
be careful about all the instances of the original list - if you mutate that, the ModList instance will mutate too
The chosen answer doesn't handle the case where the index is a negative number with a very large magnitude and the size of the list is small i.e.
Size => 10
Index => -1000000
Here is an implementation that should handle all sizes and indexes
import java.util.ArrayList;
import java.util.Collection;
/**
* A list the loops round to the first element when {#link CircularList#get(int)} is called with an
* index that is greater than the max index of the list and vice versa.
*
* #author Stuart Clark
*/
public class CircularList<E> extends ArrayList<E> {
public CircularList() {
super();
}
public CircularList(int initialCapacity) {
super(initialCapacity);
}
public CircularList(Collection<? extends E> c) {
super(c);
}
#Override
public E get(int index) {
if (isEmpty()) {
throw new IndexOutOfBoundsException("The list is empty");
}
while (index < 0) {
index = size() + index;
}
return super.get(index % size());
}
}
Does anyone know this AbstractList extension : com.sun.appserv.management.util.misc.CircularList<T>. Take a look at it. It's GlassFish java.net community solution. It should be powerful because it's used in Thread Scheduling inside GlassFish Container.
Related
I'm trying to create an iterator class that completes what I thought would be two simple methods but I am having issues I suppose creating the iterator. The line where I create the iterator is giving me a compile error saying "Iterator is abstract; cannot be instantiated". I am not too sure what that means, obviously I did something wrong though. Also I put the purpose of the methods above them, if you see anything wrong with them let me know. Thanks for any input!
import java.util.Iterator;
private class OrderedListIterator{
Iterator<E> it = new Iterator<E>();
//return true if iterator has more items
public boolean hasNext(){
boolean found = false;
if(it.hasNext == true)
found = true;
return found;
return found;
}
//return next item in the iterator
public E getNext(){
if(it.hasNext != false)
return it.next;
}
//prints out message
public void remove(){
System.out.println("Operation not supported");
}
}
The reason you are getting this error is because an iterator is an interface.
In the Java programming language, an interface is a reference type,
similar to a class, that can contain only constants, method
signatures, default methods, static methods, and nested types. Method
bodies exist only for default methods and static methods. Interfaces
cannot be instantiated—they can only be implemented by classes or
extended by other interfaces. Extension is discussed later in this
lesson.
From the Java docs https://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html
An interface contains the definition of the methods, not the implementation and is why you can't create or call interfaces or it's methods. The iterator interface has two methods; hasNext() and next(). Your code looks like you intend to implement the iterator interface.
private class OrderedListIterator implements Iterator<E>
In your hasNext and next methods, you need to iterate over your OrderedList depending on how you have implemented it.
Here is an example of an iterator for an ArrayList which I have previously created.
private class ArrayIterator implements Iterator<E> {
private int arrayIndex = 0;
/**
* Checks if the set has a next value.
*
* #return true if there is a next value, else false
*/
public boolean hasNext() {
//Checks that the index is within the size of the ArrayList
return arrayIndex < size;
}
/**
* Gets the next value in the iteration.
*
* #return
* The next value in the list
* #throws NoSuchElementException
* if there is no next element in the list
*/
public E next() throws NoSuchElementException {
if (arrayIndex == size) {
throw new NoSuchElementException();
}
//Checks the ArrayList's data at the current index
return data[arrayIndex++];
}
}
Your private class is able to access the fields from it's surrounding class. In my example, the iterator stores an index (like an internal cursor) in the array and checks the ArrayList's data at the current index. Each time the next method is called, the index is increased for the next time.
If your OrderedList class is like a LinkedList and has nodes, you would save a reference to the node and each time the next method is called you would return the node, then change the cursor to the next node.
Say, I have some class which holds an array of integers in it.
Integer[] numbers;
Also, I have some simple constructor which initializes my array:
public Program()
{
numbers = new Integer[11];
numbers[0] = null;
}
As you can see, I have an array of 11 elements.
The point is that I will never ever change the first one with index 0.
Is there a way to finalize the first element of my array, so it can't be changed?
Like with final variables.
No, you cannot do that with an array. In fact, inability to make array elements read-only is a major drawback of using arrays in situations when data could be modified externally.
The only approach to protect elements of your array is to encapsulate the array in a class that would check elements and indexes before performing modifications:
public class ArrayWithFixedFirst {
private final Integer[] numbers = new Integer[11];
public Integer get(int index) {
return numbers[index];
}
public void set(int index, Integer value) {
if (index == 0) throw new IllegalArgumentException();
numbers[index] = value;
}
}
I don't believe there is a way to specify that the first element of an array cannot be re-assigned.
I think your best bet would be to create a wrapper class for the array, and then ignore any attempts to re-assign the first element.
Through encapsulation, you can allow/disallow the array modification.
public void updateArray(int position,int value){
if(position > 0 && position < numbers.length){
numbers[position] = value;
}
}
You can not force an array to be unmodifiable. An alternative is using Collections.unmodifiableList. But the whole list will therefore be unmodifiable.
Intriguing question, but I'm going to have to say no. Java arrays will not allow you to finalize just one element. You could possibly get the same functionality by writing a custom wrapper, but that begs the question, why? I don't know what application you're going for, but I would recommend wrapping a ten element array and decrementing your index by one, and returning null for the zero'th index
I don't know why you'd do it, but something like this:
class NoFirstArray extends ArrayList {
public NoFirstArray(int size,Object initialValue) {
super(size);
super.set(0,initialValue);
}
public void set(Integer i, Object value) {
if(i == 0) throw RuntimeException();
super.set(i,value);
}
public void remove(int i) {
if(i == 0) throw RuntimeException();
super.remove(i);
}
}
My program implements a Product class whose objects contain the following instance variables: name, priority, price, and amount.
I have a LinkedList of Product objects that I need to sort before doing any other operations on the LinkedList.
I want to sort the list first by priority (from lowest to highest). If priority is the same, then look at the price (lowest to highest), then the name (alphabetical order).
I have done a lot of reading about Collections.sort, Comparable, and Comparator. I believe I need to use the Comparable interface and implement a compareTo method. My thinking is that because both priority, price, and name have a "natural" ordering it makes more sense to use Comparable.
public class Product extends ProductBase implements PrintInterface, Comparable<Product>{
private String name;
private int priority;
private int cents;
private int quantity;
// setters and getters
/**
* Compare current Product object with compareToThis
* return 0 if priority, price and name are the same for both
* return -1 if current Product is less than compareToThis
* return 1 if current Product is greater than compareToThis
*/
#override
public int compareTo(Product compareToThis)
}
Then when I want to sort my LinkedList I just call Collections.sort(LinkedList). Before I start writing the code, can you tell me if I am I missing or forgetting anything?
*************UPDATE*******************************
I just created a separate class called ProductComparator with a compare method.
This is part of the LinkedList class..
import java.util.Collections;
public class LinkedList {
private ListNode head;
public LinkedList() {
head = null;
}
// this method will sort the LinkedList using a ProductComparator
public void sortList() {
ListNode position = head;
if (position != null) {
Collections.sort(this, new ProductComparator());
}
}
// ListNode inner class
private class ListNode {
private Product item;
private ListNode link;
// constructor
public ListNode(Product newItem, ListNode newLink) {
item= newItem;
link = newLink;
}
}
}
I am getting the following error from the IDE when I compile.
The method sort(List, Comparator) in the type Collections is not applicable for the arguments (LinkedList, ProductComparator).
Does anyone know why I am getting this error and can point me in the right direction to resolve it?
If there is a "natural" ordering, use Comparable. Rule of thumb for figuring out if the ordering is "natural" is, whether the order of the objects will always be that.
Having said that, the decision whether to use Comparable or Camparator is not the kind of decision you need to think too much about. Most IDEs have refactoring tools which makes the conversion between a Comparable and a Comparator very easy. So if you choose to walk the wrong path now, changing that will not require too much effort.
The order you define here on your Product is very specific and
will probably change in future versions of your program
might be enriched with contextual parameterization
won't cover new features
So it can hardly been said "natural".
I'd suggest to define a constant, for example
public static Comparator<Product> STANDARD_COMPARATOR = new Comparator<Product>() {
public int compare(Product p1, Product p1) {
return ...
}
};
then you'll be able to easily sort anywhere with
Collections.sort(myProductList, Product.STANDARD_COMPARATOR);
Your code will evolve in a better manner as you'll add other comparators.
Just like you should generally prefer composition over inheritance, you should try to avoid defining the behavior of your objects in immutable manner.
If your order was based only on numbers, Comparable would be fine.
However, since your order (sometimes) involves lexical order of text,
a Comparator class is better, since use of Comparable would mean using
String.compareTo which would prevent you from having internationalization.
A separate class which implements Comparator can make use of a
localized Collator for comparing Strings. For instance:
public class ProductComparator
implements Comparator<Product> {
private final Collator collator;
public ProductComparator() {
this(Locale.getDefault());
}
public ProductComparator(Locale locale) {
this.collator = Collator.getInstance(locale);
}
public int compare(Product product1,
Product product2) {
int c = product1.getPriority() - product2.getPriority();
if (c == 0) {
c = product1.getPrice() - product2.getPrice();
}
if (c == 0) {
c = collator.compare(product1.getName(), product2.getName());
}
return c;
}
}
Regardless of whether you go with Comparable or Comparator, it is wise
to make sure Product has an equals method which checks the same
attributes as the comparison code.
As a sample, I am developing a simple MySortedSet<E> in java which implements SortedSet<E> interface. It is backed up with a simple array which is E[] array.
I have several questions regarding that:
This is the class: (I am not writing entire code, instead of related parts)
public class MySortedSet<E> implements SortedSet<E>, Iterator<E> {
private E[] array;
private Comparator<? super E> _comparator;
private int size = 0;
private int capacity;
#SuppressWarnings("unchecked")
public MySortedSet() {
this.capacity = 10;
this.array = (E[]) new Object[this.capacity];
// this.array = Array.newInstance(Class<E> var,int size);
// We have to get Class<E> from outside caller.
}
}
Question 1: Can somebody please tell me whether there is a better solution to create a new array in constructor instead of this this.array = (E[]) new Object[this.capacity];
ArrayList<E> stores the elements in a plain Object[], primitive values are autoboxed, and it assigns null to holes left by removed elements.
Classes that implement Comparable<E> must implement int compareTo(E other) which works similarly to compare(E o1, E o2) from Comparator. You could either check your internal comparator for null and fall back on the natural ordering of the objects, or you could define an internal "use the natural ordering" comparator implementation.
Binary search is a method of minimizing the number of comparisons needed to locate an item or the spot where an item should be inserted into a sorted list. Instead of checking each element starting with the first, you start at the midpoint of the list. If the sought item should come before the found element, shift halfway toward the front and repeat; otherwise shift halfway to the end and repeat. Each time you repeat, you use the previous lower/upper bound and the midpoint as the new sublist, halving the number of elements in each step.
Think of trying to guess a number between 1 and 100 where each time you are told whether you guessed too high or too low.
50 - too high
25 - too low
37 - too high
31 - too low
34 - too low
35 - correct!
Either you should keep doing what you're doing here, or you should keep it as an Object[] and cast the values when you're outputting them. (The ArrayList implementation, for example, does the latter.)
You can change your code to remove the unsafe cast:
public MySortedSet(Class<E> clazz) {
capacity = 10;
array = Array.newInstance(clazz, capacity);
}
Although it forces the client code to provide a Class<E> object, this is a very common code pattern used to work around this class of problem (where you need a typed Class object in a constructor).
I have a bunch of objects of a class Puzzle. I have overridden equals() and hashCode(). When it comes time to present the solutions to the user, I'd like to filter out all the Puzzles that are "similar" (by the standard I have defined), so the user only sees one of each.
Similarity is transitive.
Example:
Result of computations:
A (similar to A)
B (similar to C)
C
D
In this case, only A or D and B or C would be presented to the user - but not two similar Puzzles. Two similar puzzles are equally valid. It is only important that they are not both shown to the user.
To accomplish this, I wanted to use an ADT that prohibits duplicates. However, I don't want to change the equals() and hashCode() methods to return a value about similarity instead. Is there some Equalator, like Comparator, that I can use in this case? Or is there another way I should be doing this?
The class I'm working on is a Puzzle that maintains a grid of letters. (Like Scrabble.) If a Puzzle contains the same words, but is in a different orientation, it is considered to be similar. So the following to puzzle:
(2, 2): A
(2, 1): C
(2, 0): T
Would be similar to:
(1, 2): A
(1, 1): C
(1, 0): T
Okay you have a way of measuring similarity between objects. That means they form a Metric Space.
The question is, is your space also a Euclidean space like normal three dimensional space, or integers or something like that? If it is, then you could use a binary space partition in however many dimensions you've got.
(The question is, basically: is there a homomorphism between your objects and an n-dimensional real number vector? If so, then you can use techniques for measuring closeness of points in n-dimensional space.)
Now, if it's not a euclidean space then you've got a bigger problem. An example of a non-euclidean space that programers might be most familiar with would be the Levenshtein Distance between to strings.
If your problem is similar to seeing how similar a string is to a list of already existing strings then I don't know of any algorithms that would do that without O(n2) time. Maybe there are some out there.
But another important question is: how much time do you have? How many objects? If you have time or if your data set is small enough that an O(n2) algorithm is practical, then you just have to iterate through your list of objects to see if it's below a certain threshold. If so, reject it.
Just overload AbstractCollection and replace the Add function. Use an ArrayList or whatever. Your code would look kind of like this
class SimilarityRejector<T> extends AbstractCollection<T>{
ArrayList<T> base;
double threshold;
public SimilarityRejector(double threshold){
base = new ArrayList<T>();
this.threshold = threshold;
}
public void add(T t){
boolean failed = false;
for(T compare : base){
if(similarityComparison(t,compare) < threshold) faled = true;
}
if(!failed) base.add(t);
}
public Iterator<T> iterator() {
return base.iterator();
}
public int size() {
return base.size();
}
}
etc. Obviously T would need to be a subclass of some class that you can perform a comparison on. If you have a euclidean metric, then you can use a space partition, rather then going through every other item.
I'd use a wrapper class that overrides equals and hashCode accordingly.
private static class Wrapper {
public static final Puzzle puzzle;
public Wrapper(Puzzle puzzle) {
this.puzzle = puzzle;
}
#Override
public boolean equals(Object object) {
// ...
}
#Override
public int hashCode() {
// ...
}
}
and then you wrap all your puzzles, put them in a map, and get them out again…
public Collection<Collection<Puzzle>> method(Collection<Puzzles> puzzles) {
Map<Wrapper,<Collection<Puzzle>> map = new HashMap<Wrapper,<Collection<Puzzle>>();
for (Puzzle each: puzzles) {
Wrapper wrapper = new Wrapper(each);
Collection<Puzzle> coll = map.get(wrapper);
if (coll == null) map.put(wrapper, coll = new ArrayList<Puzzle>());
coll.add(puzzle);
}
return map.values();
}
Create a TreeSet using your Comparator
Adds all elements into the set
All duplicates are stripped out
Normally "similarity" is not a transitive relationship. So the first step would be to think of this in terms of equivalence rather than similarity. Equivalence is reflexive, symmetric and transitive.
Easy approach here is to define a puzzle wrapper whose equals() and hashCode() methods are implemented according to the equivalence relation in question.
Once you have that, drop the wrapped objects into a java.util.Set and that filters out duplicates.
IMHO, most elegant way was described by Gili (TreeSet with custom Comparator).
But if you like to make it by yourself, seems this easiest and clearest solution:
/**
* Distinct input list values (cuts duplications)
* #param items items to process
* #param comparator comparator to recognize equal items
* #return new collection with unique values
*/
public static <T> Collection<T> distinctItems(List<T> items, Comparator<T> comparator) {
List<T> result = new ArrayList<>();
for (int i = 0; i < items.size(); i++) {
T item = items.get(i);
boolean exists = false;
for (int j = 0; j < result.size(); j++) {
if (comparator.compare(result.get(j), item) == 0) {
exists = true;
break;
}
}
if (!exists) {
result.add(item);
}
}
return result;
}