Java propery way to delete an Integer from ArrayList - java

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.

Related

Creating a minimum heap of a mapping between an object and a value

The questions is in Java.
I have some sort of an Object, lets call it MyObj. Additionally, I have a way to score each instance of this object. However, the scoring depends also on another integer value. So, I use Table<MyObj,Integer,Double> valuesOf to store the values. I'd like to emphasize that I begin with a single value inserted in valuesOf, and the rest is being filled on the fly.
While filling these values, I'd like to start each time with the currently best known minimal value. When I say minimal value, I mean that over all possible instances of MyObj x and all possible integers i, I'm looking at the smallest value of valuesOf.get(x,i) that exists in valuesOf (so at first, it will be this initial value I'm putting in, and later, well, depends on the values calculated).
So the easiest way is to implement a minimum heap. To do so, I created: PriorityQueue<Double> minHeap = new PriorityQueue<>(). Then, each time a new value currNewVal has been calculated, I added valuesOf.put(x,i,currNewVal) and minHeap.add(currNewVal). Each time I want to know the current lowest value, I perform: Double currValue = minHeap.remove().
This works fine for the first iteration. The problem is, I keep knowledge only of the minimal value, and not of the x and i that resulted in this minimal value. That is, I somehow want to keep the minimal heap aware that, while I am sorting by the value of the double, I am also interested in keeping a pointer to these x and i that brought me to this value.
I read a bit about implementing comparators. And that means, that I want to create some sort of an object, lets say a combination of MyObj and an int, and then to implement a comparator for them? But this comparator will be depending on the value from the table valuesOf.
I'm not sure this is the right way to go for it. And if it is, I got a bit confused and not sure how exactly to do so. But perhaps there are better ways?
If you want to keep the keys as well as the value in a collection like a PriorityQueue need to use an object contains references to all of those values. While you could try to use generic classes like Tuple<MyObj, Integer, Double> in many cases it's best to create a more specific class that makes it easier to understand the individual components, e.g. something like this:
class HeapEntry {
private MyObj x;
private int i;
private double value;
//constructor, getters and setters omitted
}
Then use a Comparator<HeapEntry> to go along with a PriorityQueue<HeapEntry>:
PriorityQueue<HeapEntry> minHeap = new PriorityQueue(Comparator.comparingDouble(HeapEntry::getValue);
Comparator.comparingDouble(HeapEntry::getValue) is using a method reference and could also be rewritten as Comparator.comparingDouble(entry -> entry.getValue()). Before lambdas were available the comparator could have looked like this:
//creating an anonymous implementation of Comparator
Comparator<HeapEntry> heapComp = new Comparator<HeapEntry>() {
public int compare(HeapEntry left, HeapEntry right) {
//easy to do with primitives
//if you're using wrapper objects you need to deal with nulls, i.e. decide whether a null value is greater or lower than a non-null value
return Double.compare(left.getValue(), right.getValue());
}
};
Note: before the edit the code was using Comparator.comparing(...) to build the comparator which is fine is the value uses the wrapper type Double. However, since the type of value is double, i.e. the primitive type, we need to use Comparator.comparingDouble().

Deduplication using a Java Set

I have a collection of objects, let's call them A, B, C, D,... and some are equal to others. If A and C are equal, then I want to replace every reference to C with a reference to A. This means (a) object C can be garbage collected, freeing up memory, and (b) I can later use "==" to compare objects in place of an expensive equals() operation. (These objects are large and the equals() operation is slow.)
My instinct was to use a java.util.Set. When I encounter C I can easily see if there is an entry in the Set equal to C. But if there is, there seems to be no easy way to find out what that entry is, and replace my reference to the existing entry. Am I mistaken? Iterating over all the entries to find the one that matches is obviously a non-starter.
Currently, instead of a Set, I'm using a Map in which the value is always the same as the key. Calling map.get(C) then finds A. This works, but it feels incredibly convoluted. Is there a more elegant way of doing it?
This problem is not simple de-duplication: it is a form of canonicalization.
The standard approach is to use a Map rather than a Set. Here's a sketch of how to do it:
public <T> List<T> canonicalizeList(List<T> input) {
HashMap<T, T> map = new HashMap<>();
List<T> output = new ArrayList<>();
for (T element: input) {
T canonical = map.get(element);
if (canonical == null) {
element = canonical;
map.put(canonical, canonical);
}
output.add(canonical);
}
return output;
}
Note that this is O(N). If you can safely assume that the percentage of duplicates in input is likely to be small, then you could set the capacity of map and output to the size of input.
Now you seem to be saying that you are doing it this way already (last paragraph), and you are asking if there is a better way. As far as I know, there isn't one. (The HashSet API lets would let you test if a set contains a value equal to element, but it does not let you find out what it is in O(1).)
For what it is worth, under the hood the HashSet<T> class is implemented as a HashMap<T, T>. So you would not be saving time or space by using a HashSet directly ...

Methods in only Collection

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

Make default value of a "Short[]" element 0 instead of null?

I have a program that creates lists and needs any assigned values to be 0. Its been running fine when I do with int[] humpty_dumpty = new int[20]; but to optimize the size of the lists I set them to Short[] and now my program is breaking because it takes the zero's as inputs(and Short[] humpty_dumpty = new Short[20]; is making the default value null).
Is there a way to set it to default zero without having to iterate through the entire list(I can do this via a for loop but was wondering if there was a way to make its behavior similar to int)?
There is a difference between a Short[] and a short[]. Elements of the latter will be initialized to 0 because short is a "primitive" type and cannot be null. The capitalized Short class will be initialized to null because it is really just an Object wrapping a short value.
You may create an array of primitive type instead of wrapper,
short []ar=new short[20];
Short[] doesn't 'optimize the size of the lists' at all, and it has a default value of null. short[] does, and it has a default value of zero.
Answers, in order:
1) Requirement first, optimization last. Don't use sparse arrays, or try to be 'smart', unless you specifically need to do this & deal with the extra code/ overhead.
2) Use common methods (possibly in an Instance or Static Helper class) to avoid repeating common code.
eg. short sparseGet (Short[] array, int i) {return (array[i] != null ? array[i] : 0);}
3) Perhaps use short[] rather than Short[]? Uppercase types are not primitives, but Value Wrapper classes -- and stored as object references (pointers) to instances, thus slower & more memory-intensive.
4) Uppercase 'Value Wrapper' types are appropriate where you may have null values, from a database. eg. Person.Age would ideally be Integer, if there's any possibility you/ the database might not have data for that field.
Cheers.

Map generics in Java

I seem to have a bit of misunderstanding with Java Generics and I hope you can help me. I tried to create a map like so:
Map<Debater, int>
(Debater is an Interface I declared) but java complained about the int, so I did:
Map<Debater, Integer>
I suppose it's because int is not a class while Integer is, is this correct?
Also, Now I get a Debater and I need to add 1 to its value in the map. How do I do that?
Yes, you are correct.
As for incrementing:
map.put(debater, map.get(debater) + 1);
Autoboxing will take care of "switching" between the object and the primitive.
Note that this (as noted in the comments) will throw a NullPointerException if you don't have a value for this debater in the map already. So if you want to do 2-in-1, it can be reworked as follows:
map.put(debater, map.containsKey(debater) ? map.get(debater) + 1 : 1);
That's correct. A Map can only hold Objects.
Also, Now I get a Debater and I need to add 1 to it's its value in the map. How do I do that?
I suggest you to grab AtomicInteger for that so that it's more failsafe in case of multithreaded environments.
Map<Debater, AtomicInteger> map = new HashMap<Debater, AtomicInteger>();
// ...
map.get(debater).incrementAndGet();
Else you'll need to add more code to synchronize the update to avoid that threads get the "wrong" value.
I suppose it's because int is not a
class while Integer is, is this
correct?
Correct.
Also, Now I get a Debater and I need to add 1 to it's value in the map. How do I do that?
This should do the trick:
map.put(debater, map.get(debater)+1);
You're right, it's because you have to specify a class.
As for your question, you juste have to do :
myMap.put(myDebater, myMap.get(myDebater) + 1);
All conversions between int and Integer will be done by autoboxing.
You are correct about the int vs. Integer part.
To increment the value safely use:
Integer currentValue = map.get(debater);
if(currentvalue == null) {
map.put(debater, 1);
} else {
map.put(debater, currentValue + 1);
}
or you could use map.contains(debater) first if you want to handle the case that a debater is not contained in the map separately.
Java does not allow primitive types in generics. Fortunately, each of the primitive types has a "box" reference type, e.g. Integer for int, Boolean for boolean, etc. The language is aware of this association, and can do automatic boxing and unboxing for you. This means that you can do something like this:
Integer i = 5;
i++;
There are some caveats with automatic boxing/unboxing that you have to be aware of. The classic example is the following:
List<Integer> list = new ArrayList<Integer>();
list.add(3); // this is autoboxed, and calls list.add(E)
list.remove(3); // this invokes list.remove(int) overload !!!!
list.remove((Integer) 3) // this is how you call list.remove(E)
You will find that the above code as is will throw IndexOutOfBoundsException, because the first remove tries to remove the 3rd element, instead of the element 3.
You cannot use primitive type (such as int, float, char etc.) as a generic type - collections in Java are generic. That's why you have to use Integer instead of int.

Categories