Creating and array of E in Generic SortedSet - java

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).

Related

How to initialize array in Generics with mix data types

I am going through the Java Arrays and additionally, I am looking into generics. Below are the two methods of initializing an array
int[] data = {1,2,3,4,5,6,7,8,9};
// or
int[] data;
data = new int[] {1,2,3,4,5,6,7,8,9};
But when I am using generics, I have mixture of data types for example,
String[] outcome = {"0 wins", "Tie" , "X wins"};
Above array has a single data type of String. What if in an array I have something like below
outcome = {7, "Tie" , 9.0};
now I have a mixture of data types in an array. How I can write it or if it is possible to do with generics? Can I do it with ArrayList?
Thank you
I'd like to correct this:
But when I am using generics, I have mixture of data types
Generics require homogeneous data types. For instance, a List<Integer> is a list that can only ever hold an Integer, and a List<? extends Number> can only ever hold Numbers, which covers other number types like Long, Short, Double, etc...but are referred to by the single type Number.
Anyway, what you're looking for is a Bag - a collection which can hold any arbitrary object. You can implement this with an Object[] or a List<Object>, and you're going to have to check the type of each element you pull out when you want to use it, since there's no way in Java to have a heterogeneous data type, which is what you're looking for.
tl;dr: In my opinion, arrays are not a good fit for the problem, you should use objects instead.
This is not a direct answer to your question, but an answer in the form of a redesign.
First of, let us tackle your statement about generics and arrays. Arrays are covariant and retained, while generics are invariant and erased.
Covariant means that when B extends A, you can Write A[] aArray = new B[someSize];. Invariant means that this is not possible: ArrayList<A> aList = new ArrayList<B>(); will lead to a compile time error.
Retained means that the information about the type is retained at runtime: an array always "knows* what type its elements has. Erased means that the type information is gone after compilation. This is also called Type Erasure.
The mixture of covaraint and retained vs. invariant and erased has good potential to get you into trouble. That is the reason why ArrayList uses an Object[] instead of a T[] as its backing datastructure.
Now to the actual question. As was already said by others, we could go down the road ande create an Object[]. I would strongly advice against this since we loose all type information. The only way to get back that information is a instanceof check, which makes your code rigid. Imagine you change the type of an entry. In this case, the instanceof will return false, possibly leading to unwanted behavior and (best case) some test turning red or (worst case) we may not notice it.
Now how to get around this? We create a class representing (what I infer are) match results:
public class MatchResult {
private final int firstTeamScore;
private final int secondTeamScore;
public MatchResult(final int firstTeamScore, final int secondTeamScore) {
this.firstTeamScore = firstTeamScore;
this.secondTeamScore = secondTeamScore;
}
public int getFirstTeamScore() {
return firstTeamScore;
}
public int getSecondTeamScore() {
return secondTeamScore;
}
public String getResultForFirstTeam() {
if (firstTeamScore > secondTeamScore) {
return "Win"; // In an actual implementation, I would replace this with an enum
} else if(firstTeamScore = secondTeamScore) {
return "Tie";
} else {
return "Lose";
}
}
// You can add a method public String getResultForSecondTeam(), I omitted it for brevity
}
What have we won? We have types. The scores are always ints, the results always Strings. If we were, for example, change the type of the getReultforFirstTeam() from String to, e.g., an Enum, we would get compiler errors for all locations where the type does not match anymore. Thus, we hone the fail-fast design and are forced to modify the code where necessary. And thus, we do not even have the chance to get the sneaky, unwanted behaviour we had before.
1 way to handle this is that you create an array of Object, that can accommodate all of data types
Object[] outcome = {7, "Tie" , 9.0};
And later you can access objects like:
if(outcome[0] instanceof Integer){
Integer i = (Integer) outcome[0];
}
and vice versa..
outcome = {7, "Tie" , 9.0};
is simply not legal.
You can only use this syntax - an array initializer, where the element type is omitted after the equals - in a variable declaration, e.g.
Object[] outcome = {7, "Tie" , 9.0};
As mentioned earlier, you could use an Object array. Alternatively, you can use a generic class. Here's an example:
public class Queue<E> {
private ArrayList<E> queue;
/**Unparametrized constructor**/
public Queue() {
queue = new ArrayList<E>();
}
/**Enqueues an element into the queue.**/
public void enqueue(E val) {
queue.add(val);
}
/**Dequeues an element from the queue.**/
public E dequeue() {
E output = queue.get(0);
queue.remove(0);
return output;
}
/**Gets the current size of the queue.**/
public int size() {
return queue.size();
}
}
Read up on generics and how to use them.
You're going to have to create an array of objects, since all objects in java extends Object:
Object[] arr = new Object[3];
//to add objects to it:
arr[0]=new String("element at index 0");
arr[1]=new Integer(1);
arr[2]=new Character('2');
And to find if the object at index x is (for example) an Integer then your going to have to use a cast:
int x = (Integer)arr[x]; //x could be 0 or 1 or 2
Also you can do it with an ArrayList:
List<Object> listObjects = new ArrayList<Objects>();

How to fill an array with a vararg with repeat?

I'm looking for an algorithm to fill an array of a specific size with the contents of a vararg, repeating the last element of the vararg until the array is full.
public static <T> T[] fillWithRepeat(int length, T... elements) {
// make array of length "length" and fill with contents of "elements"
}
Does anyone know a good algorithm for this?
As the question doesn't include any attempt of solving the problem itself, I assume homework, thus the answer is pseudo code only:
create a new array results of length length
iterate index from 0 to length
establish an index2 variable that runs from 0 to elements.length
assign ressult[index] = elements[index2]
either increase index2, or when it reaches elements.length-1, keep it at that value
For creating a "generic" array, see here.
And of course, user Hulk is correct (again), there are utility methods Arrays.fill() and for newer Javas Array.copyOf() that you should consider using.
Here's the algorithm. It also caters for the Generic instantiation problem when you will need to instantiate an array of type T
public static <T> T[] fillWithRepeat(int length, T... elements) {
List<T> output = new ArrayList<>(Arrays.asList(elements));
for(int i = 0; i < length - elements.length; i++){
output.add(elements[elements.length - 1]);
}
return output.toArray(elements);
}

Select subarray without copying into new buffer?

I have float[] array of length 100. Is there a way I can select (pseudocode):
x = array[10:19];
To get elements 10,11,12,...,19 without copying over into another buffer? I'm in a mobile application where I don't want to waste space or time doing this. I'd rather just reference the pointers the system uses for array.
The most efficient way to do this would be to use System.arrayCopy(), which is much faster and more efficient than copying manually using a loop. It will require another array, but any approach you use (beyond just passing the original array around with a couple of ints representing the offset to use) will do this, and it's relatively cheap - the memory consuming bit is usually the objects that it's referencing rather than the array itself, and they are not copied.
No, there is no API to do that. The closest solution to this would be building your own class that wraps an existing array, and does the re-indexing:
class SubArray {
private final float[] data;
private final int offset;
private final int length;
public SubArray(float[] data, int offset, int length) {
this.data = data;
this.offset = offset;
this.length = length;
}
public float get(int index) {
if (index >= length) throw ...
return data[index + offset];
}
public void set(int index, float value) {
if (index >= length) throw ...
data[index + offset] = value;
}
}
If the result that you need is a new object that behaves like an array in all respects, including the indexing operator, you would need to make a copy.
(Update) Precondition: You should store the data in a Float[] instead of a float[], the performance-hit should be minimal.
You can use: Arrays.asList(array).subList(10, 20).
The Arrays.asList(array) does the following:
Returns a fixed-size list backed by the specified array. (Changes to the returned list "write through" to the array.) This method acts as bridge between array-based and collection-based APIs, in combination with Collection.toArray(). The returned list is serializable and implements RandomAccess.
Source
And then .subList(10, 20) returns you a List.
Then if you really want to work with arrays in the end, you could take the following lines:
List<Float> subList = Arrays.asList((Float[])array).subList(10, 20);
Float[] subArray = subList.toArray(new Float[subList.size()]);
(Update) Changed Arrays.asList(array) to Arrays.asList((Float[])array) such that it is correct now.
From documentation:
Returns an array containing all of the elements in this list in proper sequence (from first to last element); the runtime type of the returned array is that of the specified array. If the list fits in the specified array, it is returned therein. Otherwise, a new array is allocated with the runtime type of the specified array and the size of this list.
If the list fits in the specified array with room to spare (i.e., the array has more elements than the list), the element in the array immediately following the end of the list is set to null. (This is useful in determining the length of the list only if the caller knows that the list does not contain any null elements.)
Like the toArray() method, this method acts as bridge between array-based and collection-based APIs. Further, this method allows precise control over the runtime type of the output array, and may, under certain circumstances, be used to save allocation costs.
Suppose x is a list known to contain only strings. The following code can be used to dump the list into a newly allocated array of String:
Source
This should ensure that no data is wasted, the only thing to be careful about could be autoboxing.
UPDATE: Changed my answer such that it now is correct under a precondition.
What is the problem of using a simple for loop? Objects are in java called by reference.
So, executing copying the array does not copy the objects.
float[] subarray = new float[10];
for(int i = 10, j = 0; i < 19; i++, j++) {
subarray[j] = x[i];
}
The array[0] is a reference to the object of x[0].
edit: This only applies for objects, and i don't know if it also applies to a float

Circular ArrayList (extending ArrayList)

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.

How to 'remove' an Object from a Java array (can't use Collections)

As a sample, I am developing a simple MySortedSet in java which implements SortedSet 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.
}
}
Since it accepts all sort of type from primitive to reference types etc. I am not really sure when removing an item, assigning null is a good way in place of the removed item. Since Java initializes primitive types with 0. So null only works for reference types.
Below is probably very bad design:
#Override
public boolean remove(Object o) {
int indexOfElement = this.find(o);
boolean removed = false;
if (indexOfElement != -1) {
this.array[indexOfElement] = null;
removed = true;
}
return removed;
}
Can someone tell me what the best way is to remove an element from an array?
Edit:
Honestly what I am thinking to remove an element from an simple array is like copy the entire array without the removed item into a whole new array but I am not sure how efficient it would be in terms of performance and etc.
It kinda depends on the context of how you want to use your array. For example, if you are going to be iterating over the array and using the contents of it for standard methods like Arrays.sort(), they might generate NullPointerExceptions if you have null values in your array.
If you really want to remove items from an array in a safe way, I'd suggest changing your array to an ArrayList like this...
ArrayList<Object> list = new ArrayList<Object>();
list.add(object);
list.remove(object);
As this will actually remove the item from the list completely - no nulls or anything will remain, and performing methods like length() will return a real value.
For instances when I have used an array, I set the value to null, and ensure that all iterations over the array check that value != null before I try to query it. After setting the nulls for the removed items, I usually loop over the array and manually sort all the nulls to the end of the array, and then do System.arraycopy() to resize the array. This will leave you with a new array of the correct size, with all items in it except for the removed ones. However, I suggest this only if you really must use an array, as it is slower and introduces much greater potential for errors and NullPointerExceptions.
Alternatively, if you're not worried about sort-order, you can simple move the last item in the array over the top of the item you want to remove, and keep a count of the real array size. For example...
Object[] array = new Object[20];
int realSize = 15; // real number of items in the array
public void remove(int arrayIndex){
array[arrayIndex] = array[realSize-1];
realSize--;
}
This method removes an item in the array by 'replacing' it with the item in the last position of the array - its very quick and pretty to implement, if you don't care about sort order.

Categories