As OH GOD SPIDERS has pointed out in the comments there are two flavors of remove()
method available in the List
interface:
remove(Object o)
- inherited from the Collection
interface, which expects an object to remove as parameter.
remove(int index)
- defined by the List
interface, which expects the index of the element to be removed.
The compiler maps each method call to the most specific method (if there are some overloaded versions) based on the types of arguments, which in the case of nonReps.remove(indexInNonreps)
happens to be remove(Object)
because indexInNonreps
is of type Integer
.
If you unbox the indexInNonreps
into primitive int
you would face another issue - IndexOutOfBoundsException
because right after the first removal, indices in the List would no longer match the indices in the Map.
To avoid this problem and to improve the performance (removal of an arbitrary element by index from a List
is constful - in case of ArrayList
all elements to right from the removed one need to be shifted, in the LinkedList
you first need to find the target element by iterating over the list, it gives a time complexity of O(n), the same applies for removing a particular object from a list) we can firstly generate a Map
which would indicate whether a particular character is repeated or not. And then construct a List
of non-repeated characters.
That's how it might be done in O(n) time and using as fewer code as possible:
Map<Character, Boolean> isNonRepeatedByChar = new LinkedHashMap<>();
for (Character next : arr) {
// isNonRepeatedByChar.merge(next, true, (v1, v2) -> false); // does the same as to lines below
isNonRepeatedByChar.replace(next, true, false); // the key has been already encountered - changing value to false
isNonRepeatedByChar.putIfAbsent(next, true); // the key has NEVER been encountered before - adding the entry with value of true
}
List<Character> nonReps = new ArrayList<>();
for (Map.Entry<Character, Boolean> entry : isNonRepeatedByChar.entrySet()) {
if (entry.getValue()) nonReps.add(entry.getKey());
}
System.out.println(nonReps);
Output:
[b, d, f]
Note: I've used a LinkedHashMap
assuming that preserving the initial order of elements is important. If it's not the case - go with a plain HashMap
.
In case if you're comfortable with streams you can obtain the result in a single statement:
List<Character> nonReps = Arrays.stream(arr)
.collect(Collectors.toMap(
Function.identity(),
ch -> true, // the key has NEVER been encountered before - adding the entry with value of true (i.e. non-repeated)
(v1, v2) -> false, // the key has been already encountered - changing value to false
LinkedHashMap::new
))
.entrySet().stream()
.filter(Map.Entry::getValue)
.map(Map.Entry::getKey)
.collect(Collectors.toList());