Java fixed number of elements in an array - java

When I create an array in Java - int array[] and array=new int[some number] -
How can I construct it if I don't know how many values it will hold so that I have enough space in it?

In that case you might wanna use ArrayList or some other dynamic collection.
You do not have to mention the size of ArrayList and you can add as many element as you want at run time. the size grows dynamically.
Declaration
List arrayList = new ArrayList();
if using JDK 1.5 or greater then you can also mention type of elements that this list will hold.
List<String> arrayList = new ArrayList<String>();
http://www.roseindia.net/java/beginners/array_list_demo.shtml

For growing arrays, use ArrayList.
If the array should contain primitive types, you can wrap them:
ArrayList<Integer> array = new ArrayList<Integer>();
array.add(new Integer(4));
array.add(new Integer(-5));
array.add(new Integer(4));
array.add(new Integer(2));
However, when the values change a lot, you keep instantiating and throwing away Integer instances, because it is immutable. It's not very high performance either.
My solution: create a wrapper yourself, with a public value field.
This is my wrapper, which is also suitable for TreeMap and the likes, which sort items by their natural order.
public class MyInteger implements Comparable<MyInteger>
{
public int value;
public MyInteger(int value)
{
this.value = value;
}
#Override
public String toString()
{
return Integer.toString(value);
}
#Override
public int compareTo(MyInteger o)
{
return value - o.value;
}
}
Now you can do stuff like:
array.get(2).value++;

ArrayList is the simplest answer, however if you want a more memory efficient approach you can use TIntArrayList (which wraps a int[])

Related

initiate the ArrayList with maximum size

Is it possible in initiate the ArrayList with fixed size so it may not increase more than that and initiate all the initial occupancy to 0? in actual forcing it to behave like an ordinary Array so we can use the add() upto to the array size.
Why not use normal array rather than ArrayList
ArrayList are basically simply an array with support for the situation where we may have to add more items. If we're not changing the size of that ArrayList than it's just like the conventional array
You can use
List<Integer> list = Arrays.asList(new Integer[desiredLength]);
to produce a fixed size List<Integer> in which all the elements are initialized to null. Then you can use list.set(index,value) to modify elements of that List. You can't use add though, since add changes the size of the List, which is not allowed in fixed sized lists.
If you want to initialize the List to non-null values, you can do something like this :
Integer[] arr = new Integer[desiredLength];
Arrays.fill(arr,0);
List<Integer> list = Arrays.asList(arr);
You can, by using only arraylist, ensure a minimum size of the arraylist:
ArrayList<T> myArrayList = new ArrayList();
myArrayList.ensureCapacity(n);
But that doesn't set a fixed size, just something bigger than n, and it doesn't prevent you to add more than n.
As mentioned by other, you are probably better off doing something else. If you really want to achieve that, you can write your own collection:
public class MyArrayList<T> {
ArrayList<T> arrayList;
int size;
public MyArrayList(int size) {
this.size = size;
arrayList = new ArrayList<>();
arrayList.ensureCapacity(size);
}
public void add(T x) {
if (arrayList.size() >= size) {
throw new IllegalStateException();
}
arrayList.add(x);
}
//remove, etc.. . You can even extend/implement arrayList/list if you want to do polymorphism.
}

Can individual array references be made final? [duplicate]

Is there an immutable alternative to the primitive arrays in Java? Making a primitive array final doesn't actually prevent one from doing something like
final int[] array = new int[] {0, 1, 2, 3};
array[0] = 42;
I want the elements of the array to be unchangeable.
Not with primitive arrays. You'll need to use a List or some other data structure:
List<Integer> items = Collections.unmodifiableList(Arrays.asList(0,1,2,3));
My recommendation is to not use an array or an unmodifiableList but to use Guava's ImmutableList, which exists for this purpose.
ImmutableList<Integer> values = ImmutableList.of(0, 1, 2, 3);
As others have noted, you can't have immutable arrays in Java.
If you absolutely need a method that returns an array that doesn't influence the original array, then you'd need to clone the array each time:
public int[] getFooArray() {
return fooArray == null ? null : fooArray.clone();
}
Obviously this is rather expensive (as you'll create a full copy each time you call the getter), but if you can't change the interface (to use a List for example) and can't risk the client changing your internals, then it may be necessary.
This technique is called making a defensive copy.
There is one way to make an immutable array in Java:
final String[] IMMUTABLE = new String[0];
Arrays with 0 elements (obviously) cannot be mutated.
This can actually come in handy if you are using the List.toArray method to convert a List to an array. Since even an empty array takes up some memory, you can save that memory allocation by creating a constant empty array, and always passing it to the toArray method. That method will allocate a new array if the array you pass doesn't have enough space, but if it does (the list is empty), it will return the array you passed, allowing you to reuse that array any time you call toArray on an empty List.
final static String[] EMPTY_STRING_ARRAY = new String[0];
List<String> emptyList = new ArrayList<String>();
return emptyList.toArray(EMPTY_STRING_ARRAY); // returns EMPTY_STRING_ARRAY
As of Java 9 you can use List.of(...), JavaDoc.
This method returns an immutable List and is very efficient.
Another one answer
static class ImmutableArray<T> {
private final T[] array;
private ImmutableArray(T[] a){
array = Arrays.copyOf(a, a.length);
}
public static <T> ImmutableArray<T> from(T[] a){
return new ImmutableArray<T>(a);
}
public T get(int index){
return array[index];
}
}
{
final ImmutableArray<String> sample = ImmutableArray.from(new String[]{"a", "b", "c"});
}
Since Guava 22, from package com.google.common.primitives you can use three new classes, which have a lower memory footprint compared to ImmutableList.
ImmutableIntArray
ImmutableLongArray
ImmutableDoubleArray
They also have a builder. Example:
int size = 2;
ImmutableLongArray longArray = ImmutableLongArray.builder(size)
.add(1L)
.add(2L)
.build();
or, if the size is known at compile-time:
ImmutableLongArray longArray = ImmutableLongArray.of(1L, 2L);
This is another way of getting an immutable view of an array for Java primitives.
If you need (for performance reason or to save memory) native 'int' instead of 'java.lang.Integer', then you would probably need to write your own wrapper class. There are various IntArray implementations on the net, but none (I found) was immutable: Koders IntArray, Lucene IntArray. There are probably others.
The of(E... elements) method in Java9 can be used to create immutable list using just a line:
List<Integer> items = List.of(1,2,3,4,5);
The above method returns an immutable list containing an arbitrary number of elements. And adding any integer to this list would result in java.lang.UnsupportedOperationExceptionexception. This method also accepts a single array as an argument.
String[] array = ... ;
List<String[]> list = List.<String[]>of(array);
No, this is not possible. However, one could do something like this:
List<Integer> temp = new ArrayList<Integer>();
temp.add(Integer.valueOf(0));
temp.add(Integer.valueOf(2));
temp.add(Integer.valueOf(3));
temp.add(Integer.valueOf(4));
List<Integer> immutable = Collections.unmodifiableList(temp);
This requires using wrappers, and is a List, not an array, but is the closest you will get.
In some situations, it will be lighter weight to use this static method from Google Guava library: List<Integer> Ints.asList(int... backingArray)
Examples:
List<Integer> x1 = Ints.asList(0, 1, 2, 3)
List<Integer> x1 = Ints.asList(new int[] { 0, 1, 2, 3})
If you want to avoid both mutability and boxing, there is no way out of the box. But you can create a class which holds primitive array inside and provides read-only access to elements via method(s).
Implement java.util.function.IntUnaryOperator:
class ImmutableArray implements IntUnaryOperator {
private final int[] array;
ImmutableArray(int[] array) {
this.array = Arrays.copyOf(array, array.length);
}
#Override
public int applyAsInt(int index) {
return array[index];
}
}
Access the array: array[i] becomes immutableArray.applyAsInt(i).
I benchmarked primitive for loop retrieval with a modulus operation with 100_000_000 elements. The above PrimitiveArray took ~220ms; there was no significant difference with a primitive array. The same op on ArrayList took 480 ms, and the loading process took 21 seconds, depleted my heap space first try, and I had to increase this setting on the JVM. Loading of PrimitiveArray had taken 2 seconds.
iteration
if you want to iterate, implement Iterable and provide
public java.util.PrimitiveIterator.OfInt iterator() { return Arrays.stream(array).iterator(); }
This provides access to int nextInt method.
From PrimitiveIterator you also get method forEachRemaining(PrimitiveConsumer) which is helpful to replace an existing enhanced for loop.
Iterating manually with PrimitiveIterator.OfInt yielded performance of ~300ms.
While it's true that Collections.unmodifiableList() works, sometimes you may have a large library having methods already defined to return arrays (e.g. String[]).
To prevent breaking them, you can actually define auxiliary arrays that will store the values:
public class Test {
private final String[] original;
private final String[] auxiliary;
/** constructor */
public Test(String[] _values) {
original = new String[_values.length];
// Pre-allocated array.
auxiliary = new String[_values.length];
System.arraycopy(_values, 0, original, 0, _values.length);
}
/** Get array values. */
public String[] getValues() {
// No need to call clone() - we pre-allocated auxiliary.
System.arraycopy(original, 0, auxiliary, 0, original.length);
return auxiliary;
}
}
To test:
Test test = new Test(new String[]{"a", "b", "C"});
System.out.println(Arrays.asList(test.getValues()));
String[] values = test.getValues();
values[0] = "foobar";
// At this point, "foobar" exist in "auxiliary" but since we are
// copying "original" to "auxiliary" for each call, the next line
// will print the original values "a", "b", "c".
System.out.println(Arrays.asList(test.getValues()));
Not perfect, but at least you have "pseudo immutable arrays" (from the class perspective) and this will not break related code.
Well.. arrays are useful to pass as constants (if they were) as variants parameters.

How to remove duplicates of ArrayList<ArrayList<String>> and sort array

Lets say I have an array of an array of strings:
ArrayList<ArrayList<String>> arrayOfArray= new ArrayList<ArrayList<String>>();
Maybe it could look something like this(eg.):
arrayOfArray = [[A,1,B,2],[C,1,D,2],[C,1,D,2],[A,1,B,2]]
In the end I want this(duplicates was removed):
arrayOfArrayNoDuplicates = [[C,1,D,2],[A,1,B,2]]
Then as a final step I want this array of array to be sorted on the first item in the array.
Looks like this array of array maybe was sorted on the A or the B.
arrayOfArraySorted = [[A,1,B,2],[C,1,D,2]]
Is this possible without also sorting the inner array? I want to keep the order within the array "A,1,B,2".
I hope you understand want I want to do:)
/M
You use a set
It functions like an array, it dedupes
You can use a Set with a Comparator fot that.
Set<List<String>> list = new TreeSet<ArrayList<String>>(
new Comparator<List<String>>() {
public int compare(List<String> left, List<String> right) {
//check here if equal, before or after...
}
}
);
You should really use a HashSet or similar to remove duplicates from your collection of data (sets can only contain unique elements). I'm unsure how effective this will be against ArrayList's of varying contents though, so you might be best off extending ArrayList<String> and implementing your own bool equals(Object a) method (for your inner arrays).
To then sort your collection you should using Collections.sort(), you can then pass this a custom Comparator to sort them by whichever order you please. (A comparator lets you provide a method that takes 2 objects and rates their order.) Or if you've extended ArrayList<String> simply add the compare method to your class and add implements Comparator.
An example Comparator would be;
import java.util.*;
class ALComparator implements Comparator<ArrayList<String>>
{
#Override
public int compare(ArrayList<String> a, ArrayList<String> b)
{
if(a.size()==b.size())
return 1;
if(a.size()==0)
return -1;
if(b.size()==0)
return 1;
return a.get(0).compareTo(b.get(0));
}
}

Define a fixed-size list in Java

Is it possible to define a list with a fixed size that's 100? If not why isn't this available in Java?
This should do it if memory serves:
List<MyType> fixed = Arrays.asList(new MyType[100]);
A Java list is a collection of objects ... the elements of a list. The size of the list is the number of elements in that list. If you want that size to be fixed, that means that you cannot either add or remove elements, because adding or removing elements would violate your "fixed size" constraint.
The simplest way to implement a "fixed sized" list (if that is really what you want!) is to put the elements into an array and then Arrays.asList(array) to create the list wrapper. The wrapper will allow you to do operations like get and set, but the add and remove operations will throw exceptions.
And if you want to create a fixed-sized wrapper for an existing list, then you could use the Apache commons FixedSizeList class. But note that this wrapper can't stop something else changing the size of the original list, and if that happens the wrapped list will presumably reflect those changes.
On the other hand, if you really want a list type with a fixed limit (or limits) on its size, then you'll need to create your own List class to implement this. For example, you could create a wrapper class that implements the relevant checks in the various add / addAll and remove / removeAll / retainAll operations. (And in the iterator remove methods if they are supported.)
So why doesn't the Java Collections framework implement these? Here's why I think so:
Use-cases that need this are rare.
The use-cases where this is needed, there are different requirements on what to do when an operation tries to break the limits; e.g. throw exception, ignore operation, discard some other element to make space.
A list implementation with limits could be problematic for helper methods; e.g. Collections.sort.
FixedSizeList
Yes,
The Apache Commons library provides the FixedSizeList class which does not support the add, remove and clear methods (but the set method is allowed because it does not modify the List's size). Ditto for FixedSizeList in Eclipse Collections. If you try to call one of these methods, your list remains the same size.
To create your fixed size list, just call
List<YourType> fixed = FixedSizeList.decorate(Arrays.asList(new YourType[100]));
You can use unmodifiableList if you want an unmodifiable view of the specified list, or read-only access to internal lists.
List<YourType> unmodifiable = java.util.Collections.unmodifiableList(internalList);
Yes. You can pass a java array to Arrays.asList(Object[]).
List<String> fixedSizeList = Arrays.asList(new String[100]);
You cannot insert new Strings to the fixedSizeList (it already has 100 elements). You can only set its values like this:
fixedSizeList.set(7, "new value");
That way you have a fixed size list. The thing functions like an array and I can't think of a good reason to use it. I'd love to hear why you want your fixed size collection to be a list instead of just using an array.
Typically an alternative for fixed size Lists are Java arrays. Lists by default are allowed to grow/shrink in Java. However, that does not mean you cannot have a List of a fixed size. You'll need to do some work and create a custom implementation.
You can extend an ArrayList with custom implementations of the clear, add and remove methods.
e.g.
import java.util.ArrayList;
public class FixedSizeList<T> extends ArrayList<T> {
public FixedSizeList(int capacity) {
super(capacity);
for (int i = 0; i < capacity; i++) {
super.add(null);
}
}
public FixedSizeList(T[] initialElements) {
super(initialElements.length);
for (T loopElement : initialElements) {
super.add(loopElement);
}
}
#Override
public void clear() {
throw new UnsupportedOperationException("Elements may not be cleared from a fixed size List.");
}
#Override
public boolean add(T o) {
throw new UnsupportedOperationException("Elements may not be added to a fixed size List, use set() instead.");
}
#Override
public void add(int index, T element) {
throw new UnsupportedOperationException("Elements may not be added to a fixed size List, use set() instead.");
}
#Override
public T remove(int index) {
throw new UnsupportedOperationException("Elements may not be removed from a fixed size List.");
}
#Override
public boolean remove(Object o) {
throw new UnsupportedOperationException("Elements may not be removed from a fixed size List.");
}
#Override
protected void removeRange(int fromIndex, int toIndex) {
throw new UnsupportedOperationException("Elements may not be removed from a fixed size List.");
}
}
Create an array of size 100. If you need the List interface, then call Arrays.asList on it. It'll return a fixed-size list backed by the array.
If you want some flexibility, create a class that watches the size of the list.
Here's a simple example. You would need to override all the methods that change the state of the list.
public class LimitedArrayList<T> extends ArrayList<T>{
private int limit;
public LimitedArrayList(int limit){
this.limit = limit;
}
#Override
public void add(T item){
if (this.size() > limit)
throw new ListTooLargeException();
super.add(item);
}
// ... similarly for other methods that may add new elements ...
You can define a generic function like this:
#SuppressWarnings("unchecked")
public static <T> List<T> newFixedSizeList(int size) {
return (List<T>)Arrays.asList(new Object[size]);
}
And
List<String> s = newFixedSizeList(3); // All elements are initialized to null
s.set(0, "zero");
s.add("three"); // throws java.lang.UnsupportedOperationException
This should work pretty nicely. It will never grow beyond the initial size. The toList method will give you the entries in the correct chronological order. This was done in groovy - but converting it to java proper should be pretty easy.
static class FixedSizeCircularReference<T> {
T[] entries
FixedSizeCircularReference(int size) {
this.entries = new Object[size] as T[]
this.size = size
}
int cur = 0
int size
void add(T entry) {
entries[cur++] = entry
if (cur >= size) {
cur = 0
}
}
List<T> asList() {
List<T> list = new ArrayList<>()
int oldest = (cur == size - 1) ? 0 : cur
for (int i = 0; i < this.entries.length; i++) {
def e = this.entries[oldest + i < size ? oldest + i : oldest + i - size]
if (e) list.add(e)
}
return list
}
}
FixedSizeCircularReference<String> latestEntries = new FixedSizeCircularReference(100)
latestEntries.add('message 1')
// .....
latestEntries.add('message 1000')
latestEntries.asList() //Returns list of '100' messages
If you want to use ArrayList or LinkedList, it seems that the answer is no. Although there are some classes in java that you can set them fixed size, like PriorityQueue, ArrayList and LinkedList can't, because there is no constructor for these two to specify capacity.
If you want to stick to ArrayList/LinkedList, one easy solution is to check the size manually each time.
public void fixedAdd(List<Integer> list, int val, int size) {
list.add(val);
if(list.size() > size) list.remove(0);
}
LinkedList is better than ArrayList in this situation. Suppose there are many values to be added but the list size is quite samll, there will be many remove operations. The reason is that the cost of removing from ArrayList is O(N), but only O(1) for LinkedList.
The public java.util.List subclasses of the JDK don't provide a fixed size feature that doesn't make part of the List specification.
You could find it only in Queue subclasses (for example ArrayBlockingQueue, a bounded blocking queue backed by an array for example) that handle very specific requirements.
In Java, with a List type, you could implement it according to two scenarios :
1) The fixed list size is always both the actual and the maximum size.
It sounds as an array definition. So Arrays.asList() that returns a fixed-size list backed by the specified array is what you are looking for. And as with an array you can neither increase nor decrease its size but only changing its content. So adding and removing operation are not supported.
For example :
Foo[] foosInput= ...;
List<Foo> foos = Arrays.asList(foosInput);
foos.add(new Foo()); // throws an Exception
foos.remove(new Foo()); // throws an Exception
It works also with a collection as input while first we convert it into an array :
Collection<Foo> foosInput= ...;
List<Foo> foos = Arrays.asList(foosInput.toArray(Foo[]::new)); // Java 11 way
// Or
List<Foo> foos = Arrays.asList(foosInput.stream().toArray(Foo[]::new)); // Java 8 way
2) The list content is not known as soon as its creation. So you mean by fixed size list its maximum size.
You could use inheritance (extends ArrayList) but you should favor composition over that since it allows you to not couple your class with the implementation details of this implementation and provides also flexibility about the implementation of the decorated/composed.
With Guava Forwarding classes you could do :
import com.google.common.collect.ForwardingList;
public class FixedSizeList<T> extends ForwardingList<T> {
private final List<T> delegate;
private final int maxSize;
public FixedSizeList(List<T> delegate, int maxSize) {
this.delegate = delegate;
this.maxSize = maxSize;
}
#Override protected List<T> delegate() {
return delegate;
}
#Override public boolean add(T element) {
assertMaxSizeNotReached(1);
return super.add(element);
}
#Override public void add(int index, T element) {
assertMaxSizeNotReached(1);
super.add(index, element);
}
#Override public boolean addAll(Collection<? extends T> collection) {
assertMaxSizeNotReached(collection.size());
return super.addAll(collection);
}
#Override public boolean addAll(int index, Collection<? extends T> elements) {
assertMaxSizeNotReached(elements.size());
return super.addAll(index, elements);
}
private void assertMaxSizeNotReached(int size) {
if (delegate.size() + size >= maxSize) {
throw new RuntimeException("size max reached");
}
}
}
And use it :
List<String> fixedSizeList = new FixedSizeList<>(new ArrayList<>(), 3);
fixedSizeList.addAll(Arrays.asList("1", "2", "3"));
fixedSizeList.add("4"); // throws an Exception
Note that with composition, you could use it with any List implementation :
List<String> fixedSizeList = new FixedSizeList<>(new LinkedList<>(), 3);
//...
Which is not possible with inheritance.
You need either of the following depending on the type of the container of T elements you pass to the builder (Collection<T> or T[]):
In case of an existing Collection<T> YOUR_COLLECTION:
Collections.unmodifiableList(new ArrayList<>(YOUR_COLLECTION));
In case of an existing T[] YOUR_ARRAY:
Arrays.asList(YOUR_ARRAY);
Simple as that
To get a fixed-size list, you can simply use the Stream API. This will result in a fixed-size list :
List<Integer> list = Arrays.stream(new int[100])
.boxed()
.collect(Collectors.toList());
Or the old-fashioned way, This will result in a fixed-size list that is backed by the specified array:
List<Integer> list = Arrays.asList(new Integer[100]);
Yes is posible:
List<Integer> myArrayList = new ArrayList<>(100);
now, the initial capacity of myArrayList will be 100

How to get a sublist without using the sublist method in java

This is what I have right now:
public ArrayList subList(int fromIndex, int toIndex){
ArrayList a = new ArrayList();
for (int i=fromIndex;i<toIndex;i++) {
a.add(stuff[i]); //stuff is a array of strings
}
return list;
}
But is it possible to return the sublist without creating a new array? I am restrict from using any methods from the Array/ArrayList class.
If you want have the same behaviour as the Java subList method you need to retain a pointer to the original list and use an offset and length to index into the original list.
Heres a start showing the implementation of the get method.
public class SubList extends AbstractList {
private final List original;
private final int from;
private final int to;
public SubList(List original, int from, int to) {
this.original = original;
this.from = from;
this.to = to;
}
public Object get(int i) {
if (i < 0 || i > to - from) {
throw new IllegalArguementException();
}
return original.get(from + i);
}
}
public static List subList(List original, int from, int to) {
return new SubList(original, from, to);
}
To avoid creating a new list for storage, you would have to pass in a reference to the original list, keep the sublist, and then delete the remaining items from from the list, but this would leave the list missing those other items.
If that isn't your goal you will have to create a new list at some point to hold the sublist.
I assume you have to return the standard ArrayList, and not your own version of ArrayList, and I assume that 'stuff' is an array, not a list.
First off, get bonus points for making the ArrayList have the initial size of the array (toIndex - fromIndex). For more bonus points, make sure that the to and from indecies actually exist in 'stuff' otherwise you get a nice crash.
ArrayList uses an internal array for its storage and you can't change that so you have no choice but to create a copy.
EDIT
You could make things interested and much more complex but it'll impress someone... Do it by creating your own ArrayList class implementing List. Get it to use that original array. Pretty unstable since if that array is modified somewhere else externally, you're in trouble, but it could be fun.
There's three sensible things you could return. An array, a List, or an Iterator. If my assumption that you're supposed to re-implement subList was correct, then there's no way around creating the new ArrayList.
A sublist is "a new list", so you'll have to create something to represent the sublist of the array. This can either be a new array or a list. You chose an ArrayList which looks good to me. You're not creating a new array (directly), so I don't actually get that point of your question. (If you want to avoid creating a new array indirectly through ArrayList, choose another List implementation, LinkedListfor example)
If you're looking for slight improvements:
Consider passing the source array as a method parameter. Now stuff[] is a static field.
Consider initializing the new ArrayList with the size of the sublist (toList-fromList+1)
Consider using generics (only if you already now this concept). So the return type would be ArrayList<String>

Categories