basic difference between <bag> and <list> - java

I was learning Hibernate, where collections are used in hibernate. I know that bag in collection is used for mapping property of type Collection or list. And also difference betweeen bag and list is bag is unordered with duplicate allowed collection type, and in list we maintain the insertion order in collection.
1> But apart from this is there any other difference between this two?
2> I read in one book that,
bag is the lack of objects to be used as keys for the elements in
the bag, which decreases performance when updating or deleting
elements. When an element of the bag changes, Hibernate must update
all of the elements since there is no way for Hibernate to find out
which element has changed
do any one have any idea about this?

Your definition is correct. Bag works like a list without index (you don't know what is the order of elements), so it's similar to Set with duplicates.
The most important thing is to know that Hibernate can map your collections as a bag implicitly if you don't use index column in one-to-many relation. This may decrease the performance of delete/update statements and it's good to be aware of this.
Here you can find how it works internally:
http://assarconsulting.blogspot.co.uk/2009/08/why-hibernate-does-delete-all-then-re.html

When you don't want insertion order capability of list but want to allow duplicate values then you can go for bag. Here you can't go for set because it doesn't allow duplicate values.

a) BAG
Just want to add One more point. There are two types of bags 1)Bag without id's and 2) Bag with Id's.
In Bag without Id's when you remove any element, entire bag got cleared and the elements are inserted again.
But in bag with Id's, the element which has been removed only gets removed, rest of the elements are not impacted.
#ElementCollection
#CollectionTable(name = "account_user",joinColumns=#JoinColumn(name="user_id"))
#CollectionId(columns = { #Column(name = "account_user_id") }, generator = "sequence", type = #Type(type = "long"))
#Column(name = "account_provider")
private Collection<String> accountSet = new ArrayList<String>();
So if you are using bag, always try to use id bags unless you have good reason to use another.
b) List
List are also of two types, lists with order and without order.
Lists without order is similar to bag without ids.
#ElementCollection
#CollectionTable(name = "account_user",joinColumns=#JoinColumn(name="user_id"))
#Column(name = "account_provider")
private List<String> accountSet = new ArrayList<String>();
While in list with order, the data structure maintains an indexing order. So, if you remove one of the elements. rest of the elements got shifted automatically.
Hence, this type of list is used to maintain the order in which the elements are inserted into the list.
#ElementCollection
#OrderColumn(name="account_provider_order")
#CollectionTable(name = "account_user",joinColumns=#JoinColumn(name="user_id"))
#Column(name = "account_provider")
private List<String> accountSet = new ArrayList<String>();
Also, note that although ordering is persisted in the seperate column of table. It doesn't appears on the object state, when you fetch. Hence, it is just used for internal operations.

Related

Which method is more optimal for the base and sorting speed?

I currently have a list
#OneToMany(mappedBy = "movie", orphanRemoval = true, cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#OrderBy("date ASC")
private List<MovieReleaseDateEntity> releaseDates = new ArrayList<>();
entities when downloading are sorted by date.
However, as you know, the List are not the most suitable for JPA and it is recommended to use Set. That's why I have a different idea
#OneToMany(mappedBy = "movie", orphanRemoval = true, cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private SortedSet<MovieReleaseDateEntity> releaseDates = new TreeSet<>();
and implements Comparable
public int compareTo(MovieReleaseDateEntity o) {
return this.date.compareTo(o.date);
}
Which way is better? The first with a List or the second with Set?
Database are designed to execute an order by command in an optimized way while the column used in the order by is indexed.
So you should favor the ordering by the database if you can tweak the index constraints on your tables.
However, as you know, the List are not the most suitable for JPA and
it is recommended to use Set.
I would rather say that you can not abuse of the List mapping in an entity as the number of acceptable is limited for good sense reasons (cardinalities).
You can also see things more simply : if you have few elements, I suppose that using a Set is probably an acceptable way in terms of performance.
Otherwise using a List with an order by done by the database should be probably favored.
In any case, use the structure (List or Set) that seems the most fine for your use case and then measure the actual performance before changing your design to hope having better performance.
The first approach (#OrderBy("date ASC")) is sorted on database level, and second one is in memory with java implementation. If returned list is big enough in size, it's better to use first approach.
If returned collection is fairly small and you need some complex sort logic (but it's not your case with sorting by specific field), sorting with SortedSet for entity that implements Comparable might be justified.

Java - How to separate a list based on a property of it's elements

I have a list of objects which I want to perform an operation on. However I firstly need to divide the list into separate lists such that all items with the same parentID are in the same list, and then the operation is performed on each list separately (the reason being that the operation takes the parentID of the objects as a parameter).
What is the best way to separate a list based on a given property of it's elements, as required here? The highest number of objects that will be passed in the original list is < 10,000 and normally will be < 1,000.
All help is much appreciated!
It sounds like you might want to use Multimaps.index from Guava. That will build you a multi-map, where each key has a collection of elements.
The keyFunction passed into index would be a Function which just retrieves the property from a single element.
Create a
Map <IdType, List<YourObject>> map
loop thru the list, and for each id do something like
List theList = map.get(id);
if (theList == null ) {
// create a new list, add it to the map under the id
}
// add the item to theList
then you can loop thru the map's entries and you have a list of objects for each id. This approach does not require you to know how many different ids are in your list to begin with....
I would recommend writing an Iterator that wraps an Iterator, returning only elements that match what you want. You could then write an implementation of Iterable that takes an Iterable, returning such an iterator (this would allow you to use an enhanced for loop).
If you're okay with adding a 3rd party library, Google's Guava supplies various utilities which could help you out.
Specifically, use Collections2.transform like this:
Collection myOriginalList;
Collection mySplitList1 = Collections2.transform(myOriginalList, new Function() { /* method to filter out parent ID 1 */ });
... // repeat for each parent id you're interested in

When to use a Map instead of a List in Java?

I didn't get the sense of Maps in Java. When is it recommended to use a Map instead of a List?
Say you have a bunch of students with names and student IDs. If you put them in a List, the only way to find the student with student_id = 300 is to look at each element of the list, one at a time, until you find the right student.
With a Map, you associate each student's ID and the student instance. Now you can say, "get me student 300" and get that student back instantly.
Use a Map when you need to pick specific members from a collection. Use a List when it makes no sense to do so.
Say you had exactly the same student instances but your task was to produce a report of all students' names. You'd put them in a List since there would be no need to pick and choose individual students and thus no need for a Map.
Java map: An object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value.
Java list: An ordered collection (also known as a sequence). The user of this interface has precise control over where in the list each element is inserted. The user can access elements by their integer index (position in the list), and search for elements in the list.
The difference is that they are different. Map is a mapping of key/values, a list of a list of items.
I thinks its a lot the question of how you want to access your data. With a map you can "directly" access your items with a known key, in a list you would have to search for it, evan if its sorted.
Compare:
List<MyObject> list = new ArrayList<MyObject>();
//Fill up the list
// Want to get object "peter"
for( MyObject m : list ) {
if( "peter".equals( m.getName() ) {
// found it
}
}
In a map you can just type
Map<String, MyObject> map = new HashMap<String, MyObject>();
// Fill map
MyObject getIt = map.get("peter");
If you have data to process and need to do it with all objects anyway, a list is what you want. If you want to process single objects with well known key, a map is better.
Its not the full answer (just my 2...) but I hope it might help you.
A map is used as an association of a key and a value. With a list you have basically only values.
The indexes in List are always int, whereas in Map you can have another Object as a key.
Resources :
sun.com - Introduction to the Collections Framework, Map
Depends on your performance concerns. A Map more explicitly a HashMap will guarantee O(1) on inserts and removes. A List has at worst O(n) to find an item. So if you would be so kind as to elaborate on what your scenario is we may help more.
Its probably a good idea to revise Random Access Vs Sequential Access Data Structures. They both have different run time complexities and suitable for different type of contexts.
When you want to map instead of list. The names of those interfaces have meaning, and you shouldn't ignore it.
Use a map when you want your data structure to represent a mapping for keys to values. Use a list when you want your data to be stored in an arbitrary, ordered format.
Map and List serve different purpose.
List holds collection of items. Ordered (you can get item by index).
Map holds mapping key -> value. E.g. map person to position: "JBeg" -> "programmer". And it is unordered. You can get value by key, but not by index.
Maps store data objects with unique keys,therefore provides fast access to stored objects. You may use ConcurrentHashMap in order to achieve concurrency in multi-threaded environments.
Whereas lists may store duplicate data and you have to iterate over the data elements in order to access a particular element, therefore provide slow access to stored objects.
You may choose any data structure depending upon your requirement.

Difference between HashMap and ArrayList in Java?

In Java, ArrayList and HashMap are used as collections. But I couldn't understand in which situations we should use ArrayList and which times to use HashMap. What is the major difference between both of them?
You are asking specifically about ArrayList and HashMap, but I think to fully understand what is going on you have to understand the Collections framework. So an ArrayList implements the List interface and a HashMap implements the Map interface. So the real question is when do you want to use a List and when do you want to use a Map. This is where the Java API documentation helps a lot.
List:
An ordered collection (also known as a
sequence). The user of this interface
has precise control over where in the
list each element is inserted. The
user can access elements by their
integer index (position in the list),
and search for elements in the list.
Map:
An object that maps keys to values. A
map cannot contain duplicate keys;
each key can map to at most one value.
So as other answers have discussed, the list interface (ArrayList) is an ordered collection of objects that you access using an index, much like an array (well in the case of ArrayList, as the name suggests, it is just an array in the background, but a lot of the details of dealing with the array are handled for you). You would use an ArrayList when you want to keep things in sorted order (the order they are added, or indeed the position within the list that you specify when you add the object).
A Map on the other hand takes one object and uses that as a key (index) to another object (the value). So lets say you have objects which have unique IDs, and you know you are going to want to access these objects by ID at some point, the Map will make this very easy on you (and quicker/more efficient). The HashMap implementation uses the hash value of the key object to locate where it is stored, so there is no guarentee of the order of the values anymore. There are however other classes in the Java API that can provide this, e.g. LinkedHashMap, which as well as using a hash table to store the key/value pairs, also maintains a List (LinkedList) of the keys in the order they were added, so you can always access the items again in the order they were added (if needed).
If you use an ArrayList, you have to access the elements with an index (int type). With a HashMap, you can access them by an index of another type (for example, a String)
HashMap<String, Book> books = new HashMap<String, Book>();
// String is the type of the index (the key)
// and Book is the type of the elements (the values)
// Like with an arraylist: ArrayList<Book> books = ...;
// Now you have to store the elements with a string key:
books.put("Harry Potter III", new Book("JK Rownling", 456, "Harry Potter"));
// Now you can access the elements by using a String index
Book book = books.get("Harry Potter III");
This is impossible (or much more difficult) with an ArrayList. The only good way to access elements in an ArrayList is by getting the elements by their index-number.
So, this means that with a HashMap you can use every type of key you want.
Another helpful example is in a game: you have a set of images, and you want to flip them. So, you write a image-flip method, and then store the flipped results:
HashMap<BufferedImage, BufferedImage> flipped = new HashMap<BufferedImage, BufferedImage>();
BufferedImage player = ...; // On this image the player walks to the left.
BufferedImage flippedPlayer = flip(player); // On this image the player walks to the right.
flipped.put(player, flippedPlayer);
// Now you can access the flipped instance by doing this:
flipped.get(player);
You flipped player once, and then store it. You can access a BufferedImage with a BufferedImage as key-type for the HashMap.
I hope you understand my second example.
Not really a Java specific question. It seems you need a "primer" on data structures. Try googling "What data structure should you use"
Try this link http://www.devx.com/tips/Tip/14639
From the link :
Following are some tips for matching the most commonly used data structures with particular needs.
When to use a Hashtable?
A hashtable, or similar data structures, are good candidates if the stored data is to be accessed in the form of key-value pairs. For instance, if you were fetching the name of an employee, the result can be returned in the form of a hashtable as a (name, value) pair. However, if you were to return names of multiple employees, returning a hashtable directly would not be a good idea. Remember that the keys have to be unique or your previous value(s) will get overwritten.
When to use a List or Vector?
This is a good option when you desire sequential or even random access. Also, if data size is unknown initially, and/or is going to grow dynamically, it would be appropriate to use a List or Vector. For instance, to store the results of a JDBC ResultSet, you can use the java.util.LinkedList. Whereas, if you are looking for a resizable array, use the java.util.ArrayList class.
When to use Arrays?
Never underestimate arrays. Most of the time, when we have to use a list of objects, we tend to think about using vectors or lists. However, if the size of collection is already known and is not going to change, an array can be considered as the potential data structure. It's faster to access elements of an array than a vector or a list. That's obvious, because all you need is an index. There's no overhead of an additional get method call.
4.Combinations
Sometimes, it may be best to use a combination of the above approaches. For example, you could use a list of hashtables to suit a particular need.
Set Classes
And from JDK 1.2 onwards, you also have set classes like java.util.TreeSet, which is useful for sorted sets that do not have duplicates. One of the best things about these classes is they all abide by certain interface so that you don't really have to worry about the specifics. For e.g., take a look at the following code.
// ...
List list = new ArrayList();
list.add(
Use a list for an ordered collection of just values. For example, you might have a list of files to process.
Use a map for a (usually unordered) mapping from key to value. For example, you might have a map from a user ID to the details of that user, so you can efficiently find the details given just the ID. (You could implement the Map interface by just storing a list of keys and a list of values, but generally there'll be a more efficient implementation - HashMap uses a hash table internally to get amortised O(1) key lookup, for example.)
A Map vs a List.
In a Map, you have key/value pairs. To access a value you need to know the key. There is a relationship that exists between the key and the value that persists and is not arbitrary. They are related somehow. Example: A persons DNA is unique (the key) and a persons name (the value) or a persons SSN (the key) and a persons name (the value) there is a strong relationship.
In a List, all you have are values (a persons name), and to access it you need to know its position in the list (index) to access it. But there is no permanent relationship between the position of the value in the list and its index, it is arbitrary.

How do I guarantee the order of items in a collection

I have a list of objects and each and every object in the list have a position which may not change unless explicitly changed, in other words, the objects are in a queue. What collection should I use in my entity class to store these objects and how should that collection be annotated?
I currently have this
#Entity
class Foo {
...
#OneToMany(mappedBy = "foo", cascade = CascadeType.ALL)
List<Bar> bars = new ArrayList<Bar>();
...
}
If this is not possible with JPA purely, I'm using EclipseLink as my JPA provider, so EclipseLink specific annotations will ok if nothing else helps.
EDIT: Note people, the problem is not that Java wouldn't preserv the order, I know most collections do, the problem is that I don't know a smart way for JPA to preserv the order. Having an order id and making the query order by it is possible, but in my case maintaining the order id is laborious (because the user interface allows reordering of items) and I'm looking for a smarter way to do it.
If you want this to be ordered after round-tripping to SQL, you should provide some sort of ordering ID within the entity itself - SQL is naturally set-oriented rather than list-oriented. You can then either sort after you fetch them back, or make sure your query specifies the ordering too.
If you give the entity an auto-generated integer ID this might work, but I wouldn't like to guarantee it.
Use a sort order id, as Jon suggested, then add an #OrderBy annotation below the #OneToMany. This will order any query by the specified field.
As an example, if you add a new field called "sortId" to Bar, Foo would look like this:
#Entity
class Foo {
...
#OneToMany(mappedBy = "foo", cascade = CascadeType.ALL)
#OrderBy("sortId ASC")
List bars = new ArrayList();
...
}
You can
Sort a List before creation
Sort a List after creation
Use a collection that performs a sort on insert. TreeMap, TreeSet
A linked list implements the Queue inteface in java and allows you to add things in the middle...
TBH most of the collections are ordered aren't they...
Check the docs, most say whether or not they are ordered.
It's worth trying LinkedList instead of ArrayList, however, as Jon said, you need to find a way of persisting the order information.
A solution will probably involve issuing an order number to each entry an storing it as a SortedMap, when converting into the List, if List is that you need.
However, ORM could potentially be clever enough to do all the conversions for you if you stored the collection as LinkedList.

Categories