I have an array which size does not change during the execution of my program. Let's say there are multiple threads which are changing the content of this array, something like
array[validIndex] = new Entity();
Is it safe to iterate through such array at any point in time? Let's say that I don't care about the objects which are "inside" the array.
Array sizes in Java don't change...ever.
Iterating through an array is essentially looping through array indices and getting the element at each index -- whether you do it explicitly, or you use the shiny for( Entity e: array ) ... syntax -- so there's no way the iteration itself will go wrong, even with changing array contents.
The objects you're going to see through the iteration may not constitute a valid "snapshot" of the contents of the array at any given point in time, but as far as I understand, this is not an issue in your case.
You can make array thread safe as follows:
list arryList = new ArrayList();
list arratListNew= Collections.synchronizedList(arrayList);
//Here arratListNew will be threadsafe array.
Related
I planned to make a wrapper to Swift MT203, MT204 messages.
Message Structure as follows,
MT203 -
2 Mandatory Sequences, where first one exists once and second one can exists two to ten times, and each sequence can contains mandatory fields and optional fields.
MT204 -
2 Mandatory Sequences, where first one exists once and second one can exists more than one time, and each sequence can contains mandatory fields and optional fields.
[References for the MT203 and MT204]
https://www2.swift.com/knowledgecentre/publications/usgf_20180720/1.0?topic=finmt203.htm
https://www2.swift.com/knowledgecentre/publications/usgf_20180720/1.0?topic=finmt204.htm
Which data structure is better to use to store the second sequences in each cases,
I prefer, Array for instance MT203, since I know the maximum size of second sequence but for MT204 I was confused to choose which is better from array and array list.
As during unpacking we have to get fields continuously but not all fields are mandatory for the second sequences.
[Also do comment if the first one choice of Array is not valid]
I think you'd do quite fine with either data structures.
Having said that, there's some things you might want to consider: you can make an ArrayList (like any other list) Immutable. That will prevent unwanted modification of the contents. This might be very interesting when you pass these message objects around and want to prevent someone else to modify the message accidentally. There's many ways to make a list immutable - such as Collections.immutableList(myArrayList) or Guava's ImmutableList.copyOf(myArrayList).
Having said that, I believe that there are more important considerations than features of lists over features of array:
First of all, I would consider having them both use the same data structure - especially if both messages are used in the same part of the codebase, it's going to be very confusing if one message type is an array, while the other one is a list. This might ultimately become a pain in the back as both messages will have to be handled differently. e.g. if you want to log messages - you'll have to do that differently for lists vs arrays.
Secondly, I would recommend, modelling each of these messages as a class. That class would (obviousely) use an array or a list internally to store the message data, but it would also give higher level semantical access to the contents of the message.
say you wanted the ValueDate of MTS203 (field index 1): you'd always need to call dateFormat.parse(message[1]) for that - and everyone would need to remember what index 1 was and how to parse the date string into an actual date object. If you had a class like this:
class MultipleGeneralFinancialInstitutionTransfer {
private List<String> messageData;
/** constructor... */
public Date getValueDate() {
return parseDate(messageData.get(1)); // imagine parse date being a method to parse the actual format
}
}
it would be much more convenient to work with that message - and nobody would need to remember the actual format of that message.
I. Size: Array in Java is fixed in size. We can not change the size of array after creating it. ArrayList is dynamic in size. When we add elements to an ArrayList, its capacity increases automatically.
II. Performance: In Java Array and ArrayList give different performance for different operations.
add() or get(): Adding an element to or retrieving an element from an array or ArrayList object has similar performance. These are constant time operations.
resize(): Automatic resize of ArrayList slows down the performance. ArrayList is internally backed by an Array. In resize() a temporary array is used to copy elements from old array to new array.
III. Primitives: Array can contain both primitive data types as well as objects. But ArrayList can not contain primitive data types. It contains only objects.
IV. Iterator: In an ArrayList we use an Iterator object to traverse the elements. We use for loop for iterating elements in an array.
V. Type Safety: Java helps in ensuring Type Safety of elements in an ArrayList by using Generics. An Array can contain objects of same type of classe. If we try to store a different data type object in an Array then it throws ArrayStoreException.
VI. Length: Size of ArrayList can be obtained by using size() method. Every array object has length variable that is same as the length/size of the array.
VII. Adding elements: In an ArrayList we can use add() method to add objects. In an Array assignment operator is used for adding elements.
VIII. Multi-dimension: An Array can be multi-dimensional. An ArrayList is always of single dimension
Now you can chose as per your need which is better for you
assume the following code:
ArrayList<A> aList = new ArrayList<>();
for(int i = 0; i < 1000; ++i)
aList.add(new A());
A anElement = aList.get(500);
for(int i = 0; i < 100000; ++i)
aList.add(new A());
Afterwards anElement still correctly references aList[500], even though the ArrayList presumably reallocated its data multiple times during the second for loop. Is this assumption incorrect, and if not, how does Java manage to have anElement still point at the correct data in memory?
My theories are that either instead of freeing the memory anElement references, that memory now points to the current aList data, or alternatively the reference anElement has is updated when growing the array. Both of these theories however have really bad Space/Time Performance implication, so I consider them unlikely.
Edit:
I misunderstood how arrays store elements, I assumed they store them directly, but in reality they store references, meaning that anElement and aList[500] both point to some object on the heap, solving the problem I failed to understand!
When array that internally stores elements of an ArrayList becomes full, new, larger array is being created and all elements from the previous array are being copied to new one at the same indexes and now there is a space for new elements. Garbage collector will get rid of previous, not needed any more array.
You might want to have a look at the code of implementation of ArrayList here to see details of how it works "under the hood".
Second loop in your code, added next 100000 elements after the 1000th element so now you have 101000 elements in aList, first 1000 elements weren't moved anywhere. With get() method you only read that element, nothing is moved nor deleted from that ArrayList.
Note that ArrayList doesn't really work like array (e.g. array of As is A[]) and it's not a fixed-size collection - ArrayList changes its size when adding or removing elements - e. g. if you remove element at index 0 (aList.remove(0);), then element that was stored at index 1000 is now stored at index 999 and size of ArrayList also changes from 1000 to 999.
If you want to know how an ArrayList works internally just look at the sources you can find online, for example here:
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/ArrayList.java
Here you can clearly see that an Object[] is used internally that is resized to int newCapacity = (oldCapacity * 3)/2 + 1; when deemed neccessary.
The indexes stay the same, as long as you add something to the back. Should you insert something in the middle all indexes of elements behind this are incremented by one.
That is not Java, but an implementation detail of the given JVM. You can read something here: https://www.artima.com/insidejvm/ed2/jvm6.html for example, so there are complete books about JVM internals.
A simple approach is to have a map of objects, so you refer that map first, and then find the current location of the actual object. Then it is simple to move the actual object around, as its address is stored in a single copy, in that map.
One could say this is slow and store address directly, and go without the extra step of looking up the object in a map. This way moving the object around will require more work, though still possible, just all pointers have to be updated (as raw pointers do not appear on the language level, casting to numbers temporarily or storing inside some random array and similar magic can not do harm here, you can always track that something is a pointer pointing the object you are moving around or not).
So I just discovered that Java allows us to create arrays of size 0. Does that mean that the array is both empty and full at the same time? I figured this out while working on an array based implementation of a priority queue. Would it be right to say that it is empty and full at the same time when calling methods checking for this? Or should I not allow the creation of an array of size 0? Thanks.
Java arrays have no definition of full or of empty. Consider
int[] foo = {0};
int[] bar = new int[1];
Is foo full because it has a value assigned to its only position?
Is bar empty because it has no values assigned?
Both arrays are the same, they both have one value stored and in both cases the contain the value 0.
Full implies you can't add any more items, you can never add new items to java arrays, just replace existing items, so either all arrays are full or full does not make sense for a java array. I say it is the second.
I am wondering what is the time complexity [in big O(n) notations] of ArrayList to Array conversion:
ArrayList assetTradingList = new ArrayList();
assetTradingList.add("Stocks trading");
assetTradingList.add("futures and option trading");
assetTradingList.add("electronic trading");
assetTradingList.add("forex trading");
assetTradingList.add("gold trading");
assetTradingList.add("fixed income bond trading");
String [] assetTradingArray = new String[assetTradingList.size()];
assetTradingArray.toArray(assetTradingArray);
similarly, what is the time complexity for arrays to list in the following ways:
method 1 using Arrays.asList:
String[] asset = {"equity", "stocks", "gold", "foreign exchange","fixed
income", "futures", "options"};
List assetList = Arrays.asList(asset);
method 2 using collections.addAll:
List assetList = new ArrayList();
String[] asset = {"equity", "stocks", "gold", "foreign exchange", "fixed
income", "futures", "options"};
Collections.addAll(assetList, asset);
method 3 addAll:
ArrayList newAssetList = new ArrayList();
newAssetList.addAll(Arrays.asList(asset));
The reason I am interested in the overhead of copying back and forth is because in typical interviews, questions come such as given an array of pre-order traversal elements, convert to binary search tree and so on, involving arrays. With List offering a whole bunch of operations such as remove etc, it would make it simple to code using List than Array.
In which case, I would like to defend me for using list instead of arrays saying "I would first convert the Array to List because the overhead of this operation is not much (hopefully)".
Any better methods recommended for copying the elements back and forth from array to list that would be faster would be good know too.
Thanks
It would seem that Arrays.asList(T[]); is the fastest withO(1)
Because the method returns an unmodifiable List, there is no reason to copy the references over to a new data structure. The method simply uses the given array as a backing array for the unmodifiable List implementation that it returns.
The other methods seem like they copy each element, one by one to an underlying data structure. ArrayList#toArray(..) uses System.arraycopy(..) deep down (O(n) but faster because it's done natively). Collections.addAll(..) loops through the array elements (O(n)).
Careful when using ArrayList. The backing array doubles in size when its capacity is reached, ie. when it's full. This takes O(n) time. Adding to an ArrayList might not be the best idea unless you know how many elements you are adding from the beginning and create it with that size.
Since the backing data structure of ArrayList is an array, and copying of an array elements is a O(n), it is O(n).
The only overhead I see is pollution of heap with those intermediate objects. Most of the time developers (especially, beginners) don't care about that and treat Java GC as a magic wand that cleans everything after them. My personal opinion is, if you can avoid unwanted transformation of array to list and vice versa, do that.
If you know beforehand the foreseeable (e.g. defined) size of a list, preallocate its size with ArrayList(int size) constructor to avoid internal array copying that takes place inside ArrayList when capacity is exhausted. Depending on a use case, consider other implementations, e.g. LinkedList, if you're only interested in consequent addition to the list, and iterative reading.
An ArrayList is fundamentally just a wrapper around an Object[] array. It has a lot of helpful methods for doing things like finding items, adding and removing items, and so on, but from a time complexity perspective these are no better than doing the operations yourself on a plain array.
If your hope is that an ArrayList is fundamentally more efficient than a manually managed array, it's not. Sorry!
Converting an array to an ArrayList takes O(n) time. Every element must be copied.
Inserting or removing an element takes O(m) amortized time, where m is the number of elements following the insertion/removal index. These elements have to be moved to new indices whether you use an array or ArrayList.
"Amortized" means average -- sometimes the backing array will need to be grown or shrunk, which takes additional time on the order of O(n). This doesn't happen every time, so on the whole the additional time averages out to an O(1) additional cost.
Accessing an element at an arbitrary index takes O(1) time. Both provide constant time random access.
I want to make a hash table class in java where I store the key,value pairs in an ArrayList of Linked List's. I do this by declaring
ArrayList<LinkedList<T>> storage = new ArrayList();
I then want to create a linkList object that I can use to then create a new linked list inside of each index of the arrayList. I do this by declaring:
LinkedList<T> list = new LinkedList<T>();
Then I have my add function set up to add elements to the first index of the LinkedList that is inside the Hashed key index of the arrayList as such:
public void add(K key, T value){
int arrayListIndex = (key.hashCode()) % this.initialCapacity;
System.out.println(arrayListIndex); //This tells us where we access the Array List;
if (hashBrown.get(arrayListIndex) == null){
hashBrown.add(arrayListIndex, list);
hashBrown.get(arrayListIndex).addFirst(value);
}
}
Everytime I run this code I receive an error where my index is 7 and my size is 0. This causes an error:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 7, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:571)
at java.util.ArrayList.get(ArrayList.java:349)
at FastHashtable.add(FastHashtable.java:72)
at FastHashtable.main(FastHashtable.java:145)
I am unable to track down where this index out of bounds error is coming from can anyone offer advice. I am fairly new at working with ArrayLists which makes me think my original declaration of the arrayList is incorrect.
You are confusing an ArrayLists capacity with its size. From the Oracle Java documentation:
Each ArrayList instance has a capacity. The capacity is the size of the array used to store the elements in the list. It is always at least as large as the list size. As elements are added to an ArrayList, its capacity grows automatically. The details of the growth policy are not specified beyond the fact that adding an element has constant amortized time cost.
Instead, you should be looking at creating a plain array (e.g. Object[] a = new Object[maxSize]) in which you can actually assign objects (linked lists in this case) at arbitrary index values. If you only want to store linked lists, create a LinkedList<T>[] array.
You cannot add to a list at index 7 if there are 0 elements in it. You can only add at the end (with the add method without index) or at a position that is no larger than the current list's size().
When the list is empty and you add something at index 7, what do you expect the list to contain at the first position then, and what at index 6? (I once created a subclass of list to fill everything up to the index with null when the addition index is larger than the list size, but this behaviour is not universal enough to be part of List's semantics.
[edit in response to comment here and to praseodym's answer]
You could simply fill the (array) list with nulls replace those with a linked list when the respective position is first accessed. (Be sure to use set and not add, though, which is probably what you want above as well.)
Alternatively, you could create an array of the desired size (that will be full of nulls by default) and "wrap" it into a (non-resizable) list via Arrays.asList. You have to ignore an "unchecked conversion" warning then, however (not that you could avoid warnings when using an array). Also, I suggest you read "Program to an interface, not an implementation".