Methods in only Collection - java

A HW question
You are given a list, L , and a another list, P, containing integers sorted in ascending order. The operation printLots(L,P) will print the elements in L that are in positions specified by P. For instance, if P=1,3,4,6, the elements in positions 1,3,4, and 6 in L are printed. Write the procedure printLots(L,P). The code you provide should be the java method itself (not pseudocode), the containing class is not necessary.
You may use only the public Collection https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html methods that are inherited by lists L and P. You may not use methods that are only in List. Anything that the Collection methods return is fair game, so you might think about how to use iterators.
Hi all, above all is a part of a problem. I am very confused about what it means. I am not very familiar with Collection and lists. So does this requirement means that I cannot use methods such as get() and instead have to use Iterator?
Here is my code:
public static void printLots(List<Integer> L, List<Integer> P){
int size = L.size;
for(int i=0; i<P.size; i++){
int pos = P.get(i);
if(P.get(i) <= size){
int val = L.get(pos);
System.out.println(val);
}
else{
System.out.println("It has exceeded the number of elements in L");
}
}
}

No, you cannot use List.get(idx).
I think they are trying to get you to think about a more "interesting" way of doing it. Collection does technically defined a toArray method that you could use, but it's probably against the spirit of the problem you have been set.
Collection also has a contains method, so you could iterate over your first list, increment a counter, and see if the second contains that index each time. If so, print it. It's a very inefficient way, but it would satisfy the problem.
I would suggest changing the declaration of your parameters to Collection<Integer> instead, that way the compiler will prevent you from accidentally using methods that exist in List

I'd suspect that you're right and .get(int) is not allowed.
Since positions in P are given in ascending order, it's easy to use an iterator and keep a counter of the element currently "iterated at". The counter is also strictly ascending.
A "cheat" would be to use .toArray() and use index access in it :)

Related

If some function parameter recieves List<List<Integer>> nums , then the nums is instantiated by LinkedList or ArrayList?

Both LinkedList and ArrayList are built on the List interface, yet the LinkedList uses the traditional pointer technique to build a list, and ArrayList uses array to implement List functionality . So what can one claim before using the nums will it be using ArrayList or LinkedList behind the screen?
How I got this question?
public int[] smallestRange(List<List<Integer>> nums) {
}
}
Most of The Leetcode Java question has this format of the input. Without the prior knowledge of how the nums have been instantiated, how can someone use nums.get(i) function (list.get(i) is O(1) in ArrayList and O(n) in linkedList )
99% of the time, it'll be an ArrayList, and you want to use an ArrayList in your code. They use less memory, are faster, and code taking advantage of LinkedList can usually be rewritten to use two ArrayLists. The main downside is add() occasionally running in O(n) time.
how can someone use nums.get(i)
You don't. You take advantage of the list being Iterable and do things like for-each loops:
for (var i : list) {
...
}
this runs in O(n) time for both LinkedList and ArrayList.
Technically, there's an interface called RandomAccess you can check to see if get() is O(1). You probably don't want it, though. Use the iterator.
if (list instanceof RandomAccess) {
list.get(...);
}
You can't directly predicate that what is default implementation of the List Interface. Interface is just a specification and you have multiple implementations of List Interface like you have mentioned in the image.
Every implementation will just override the method that mentioned in the List interface but their logic will be different based on the data structure.
Now its totally depend upon you which implementation you want based on your requirement. Whether you have space constraint or time constraint. But both will have same method as they are specified in interface.
As per coding challenges platform I think they specify the code from where they have call this method. You can check there But if it is not specified then most probably they will choose ArrayList - for time constraint. And I think a user should not be worried about the implementation that the they chosen. As I told user should know what is his requirement and then only choose implementations.
It can be either of them:
List<List<Integer>> list1 = new ArrayList<>();
List<List<Integer>> list2 = new LinkedList<>();
int[] x = smallestRange(list1); //works
int[] y = smallestRange(list2); //also works
You need to make your code be able to cater to both types

Java - Data structure design - Fixed size, random access, thread safe, sorted collection

So, in some question I was required to implement the following:
Data structure of fixed size (n=10), that is always ordered (descending, not that it matters), thread safe, and supports random access.
My solution was - using a TreeSet, whenever adding an element, if there are already n elements, remove the smallest element (if the new element if bigger than it) and add the new element. Otherwise, just add the new element.
When accessing a random index, use the TreeSet iterator to iterate until the required index.
I don't like this solution so much. So I thought of another solution:
Using an ArrayList, constructed with the size of n. Whenever trying to add an element, do a Collections.binarySearch() for the element and insert it if it doesn't exists, using the index returned from binarySearch. If after adding the element the list length is bigger than n (equals n+1 actually), remove the smallest element (which is on the end of the list). This way, we get log(n) for add (same as TreeSet from previous solution) and random access is O(1). Only thing I don't like about it is that the add() for an arbitrary index in the middle of the list requires shifting all the elements after it. (works well for small n but for big n maybe not?)
For both solutions I use ReentrantReadWriteLock - acquire writeLock() for add and readLock() for the get() / read operations.
Is there a better solution?
**
Collections.synchronizedList(List i) makes the passed argument a threadsafe List.
you can implement the comparable interface when creating your class and override compareTo() method in a way that it orders the element by descending order when you are adding them to the ArrayList<>() or you can go for Comparator class and overriding compare() method while sorting it.
In the total collection, only List(I) supports RandomAccess.
ArrayList<Employee> arrayList = Collections.synchronizedCollection(new ArrayList<Employee>(10));
and if you want the same item should not be added to the ArrayList use Comparator and return 0 when a new item (want to add) and last item (already added) is equal. handle the return value in such a manner that if (...==0){ don't add to the data ) else { add it }.
I hope I could give u some hint.

How to increase the performance with Java ArrayList

I'm using a huge ArrayList with the code bellow
public final List<MyClass> list = new ArrayList<>();
public void update(MyClass myClass) {
int i;
for (i=0; i < list.size(); i++) {
if (myClass.foo(list.get(i))) {
list.set(i, myClass);
break;
}
}
if (i == list.size()) {
list.add(myClass);
}
}
The list is extremely large. There is something else that I can do to increase the performance with this scenario? Maybe using some Java 8 feature, replacing ArrayList or something like that.
Another code that is taking too long to run related this List is the code bellow:
public List<MyClass> something(Integer amount) {
list.sort((m1, m2) -> Double.compare(m2.getBar(), m1.getBar()));
return list.stream()
.limit(amount)
.collect(Collectors.toList());
}
Any help is welcome, thank you all
It seems like the choice of the ArrayList is not good.
In the first case, you attempt to find an object by his properties in the list. To find an object in the list, you have to check in each elements of your list. Bigger is the list, the longer it will be. (You have a worst case complexity of O(N) with ArrayList)
If you use an HashMap instead of a List, you can use your property as key of your map. Like this, you can select the object you need to update directly without check each element of your list. The execution time will be no more dependent of the number of entries. (You have a worst case complexity of O(1) with HashMap)
If you use HashMap instead of ArrayList, your update code gonna look like this:
public void update(MyClass myClass) {
map.put(myClass.getKey(), myClass);
}
(where getKey() is the properties you try to equals in your foo method).
But this is only for the first case. With the informations we have it seems the best solution.
There is something else that I can do to increase the performance with this scenario?
The problem is that your algorithm has to apply myClass.foo to every element of the list until you find the first match. If you do this serially, then the worst-case complexity is O(N) where N is the list size. (And the list size is large.)
Now, you could do the searching in parallel. However, if there can be multiple matches, then matching the first one in the list is going to be tricky. And you still end up with O(N/C) where C is the number of cores available.
The only way to get better than O(N) is to use a different data structure. But without knowing what the MyClass::foo method does, it is hard to say what that data structure should be.
Your second problem seems to be trying to solve the "top K of N" problem. This can be implemented in O(N log K) and possibly better; see Optimal algorithm for returning top k values from an array of length N.

Java propery way to delete an Integer from ArrayList

I have an array list of integers and would like to delete an Integer value from it. To clarify: Let's say I have a function that takes in an ArrayList of Integers, and specified Integer value. I need to return the list with (value+1) deleted from it.
boolean deleteFromList(ArrayList<Integer> list, Integer value)
Now, if I do this:
return list.remove(value+1)
compiler will complain because it will try to invoke the delete method that takes int parameter and deletes an object from specified location, not the actual object.
So what is a proper way to deal with this? Is it better to do:
list.remove((Integer)(value+1))
or
int v = value.intValue();
v++;
list.remove(new Integer(v));
? In the second case, can I be sure the right value will be deleted?
list.remove(value+1) will remove at given index.
You can use list.remove(Integer.valueOf(value+1)) to remove the Integer.
Integer.valueOf(v) is recommanded instead of new Integer(v) because it allows reuse of Integer instances for special values (see javadoc).
EDIT :
In term of boxing/unboxing, it is possible to completely eliminate the problem using libraries like trove4j which define an dynamic array of integer storing the primitive values instead of numeric class (see TIntArrayList). No boxing, no unboxing, lower GC use and better performance.
In the second case, can I be sure the right value will be deleted?
Yes you can.
The remove method will use equals(Object) to identify the object to be removed from the list. Since Integer.equals compares by value (not by object identity), it doesn't matter how you created the Integer instances ... provided the wrapped int values are the same.
However ... your second version is inferior to the first version:
It cumbersome: 3 statements instead of 1.
You are using new Integer(...) rather than Integer.valueOf(...) which is always going to create a new instance. By contrast, autoboxing (or calling Integer.valueOf(...) explicitly) makes use of the Integer classes instance cache, and that will often avoid creating a new instance.
list.remove(Integer.valueOf(value+1));
should work fine.
Do you looking for this one.
Collections.sort(list);
int index = list.indexOf(5);
list = list.subList(0, index-1);
System.out.println(list);
You can use list.indexOf(value + 1) since that method only takes the object. Then use that index to remove the element.
int i = list.indexOf(value + 1);
list.remove(i);
If you need to remove all instances of value + 1 then continue until i is -1 (not found).
Or, just iterate over it and remove as you find them
for (Iterator<Integer> iterator = list.iterator(); iterator.hasNext(); ) {
Integer integer = iterator.next();
if (integer == value + 1) {
iterator.remove();
}
}
A more effective way might be to use a TIntArrayList from Trove4j library which wraps int[] array and doesn't use wrapper types. For this reason it takes 3x times less memory and is much faster.

Sorting an Array in Java

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.
}
}
Question 3: There is a explanation for Constructor since this is a sorted set so it is assumed the elements are sorted:
If this constructor is used to create the sorted set, it is assumed
that the elements are ordered using their natural ordering (i.e., E
implements Comparable).
It gets two different constructor. One is parameterless and the other one is accepting Comparator<? super E>.
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.
}
public MySortedSet(Comparator<? super E> comparator) {
this._comparator = comparator;
}
If comparator is not passed in, natural ordering should be used but I am not really sure how to accomplish it as I need to get Comparator in some way to access compare method. Do you guys please recommend me a way to call it so I can call it while comparing in sort method to sort each element.
For whom they like to see whole code, please refer to this address: http://codepaste.net/4ucvsw it is not perfect but I am working on it.
Question 4: The code guide says :
Because the fastest way to search for a particular item is to use a
binary search, you must ensure that the items in the collection are in
sorted order at all times. This won't be as hard to achieve as it may
seem. When you insert a new item, you can assume the array you are
inserting it into is already sorted. So all you need to do is find the
position in the array where the new item belongs, shift everything
greater than the new item one slot to the right, and insert the new
item. This is called insertion sort.
Here is the sort method logic. I am needed to make binary search to find where a new item belongs to so I can insert the new item in that place and move the other one slot to the right.
But I am not really sure how binary search will work for me here since I am not really sure what I need to find. I am given the item to add not the item to find. Instead what I think is to compare each element with the one I need to add and when I find the last smaller and first greater item, then I will get the first greater item's index, move them to the right and add new item at the index.
Question 3:
The fact is that every collection works with a predefined comparator, which is implicitly defined on the E, so that every class that will be used to concretize the type parameter E should implement Comparable<E>. The compare method you are looking for natural ordering is the method
int compareTo(E other)
that must be implemented by the classes that you are going to use with your data structure. Since your work is not related to defining classes to be used with your collection but just the collection itself what you are going to do it to have
public class MySortedSet<E> ... {
private Comparator<? super E> _comparator;
public int innerCompare(E e1, E e2)
{
if (_comparator != null)
return _comparator.compare(e1,e2);
else
return e1.compareTo(e2);
}
...
So that you'll use a custom comparator when provided, the natural one otherwise.
Both Comparable and Comparator work by following the same principle but the first one, as the name states, is attached to a data class, so that it is its natural comparator. The latter, instead, is used because it allows you to define a custom way to sort elements which would be sorted in a different way according to natural ordering.
Question 4:
What it means is that, under the assumption of having a sorted array, you just must keep this constraint valid after every insertion and you will be allowed to do binary search when looking for items.
You must focus just on placing the elements at correct index (the item you have to add). The part of the statement related to finding elements must be interpreted in the following way:
if you take care of keeping your array sorted, that can be done by ensuring that every element you add is placed in right position (eg with insertion sort), then you can apply binary search on the array when looking if an element is contained in the set.
This is true because, if the array is sorted, you can be sure that looking at the middle element of a section of the array will always point you to the right direction to see if another element is indeed contained in the list.
EG:
1, 2, 6, 11, 21, 30, 45
You need to check for 2, you can take element at index size()/2 = 3, which is 11. Since your already know that the array is sorted and 2 < 11 you can just do the same thing recursively on the left half and so on.
Answer 3:
"Natural ordering" means that the elements must implement Comparable so that they can be compared without the use of a Comparator. The tricky part about giving the caller a choice between Comparable elements and a Comparator is that you can't do compile time checking to make sure they fulfilled at least one of these requirements.
Java's TreeSet similarly exposes a constructor that takes a Comparator and others that don't. TreeSet's contract is essentially to throw a ClassCastException if you try to insert an element that isn't a Comparable if you didn't provide the TreeSet with a Comparator when you created it. Whether you want to use this strategy or another one is up to you.
Answer 4:
Based on the quote's strategy, you should be able to use Arrays.binarySearch(Object[], Object) for this exact purpose. From that method's documentation:
Returns: index of the search key, if it is contained in the array;
otherwise, (-(insertion point) - 1). The insertion point is defined as
the point at which the key would be inserted into the array: the index
of the first element greater than the key, or a.length if all elements
in the array are less than the specified key. Note that this
guarantees that the return value will be >= 0 if and only if the key
is found.

Categories