How to Compare element of Arraylist<Integer> - java

I wrote below code to get duplicate elements from Arraylist. My aerospikePIDs list doesn't have any duplicate value but still when I am executing below code it is reading if condition.
ArrayList<Integer> aerospikePIDs = new ArrayList<Integer>();
ArrayList<Integer> duplicates = new ArrayList<Integer>();
boolean flag;
for(int j=0;j<aerospikePIDs.size();j++) {
for(int k=1;k<aerospikePIDs.size();k++) {
if(aerospikePIDs.get(j)==aerospikePIDs.get(k)) {
duplicates.add(aerospikePIDs.get(k));
flag=true;
}
if(flag=true)
System.out.println("duplicate elements for term " +searchTerm+duplicates);
}
}

Your inner loop should start from j + 1 (not from 1), otherwise when j = 1 (second iteration of j), for k = 1 (first iteration of k for j value equals to 1).
aerospikePIDs.get(j)==aerospikePIDs.get(k)
returns true.
So the code should be:
ArrayList<Integer> aerospikePIDs = new ArrayList<Integer>();
ArrayList<Integer> duplicates = new ArrayList<Integer>();
for (int j = 0; j < aerospikePIDs.size(); j++) {
for (int k = j + 1; k < aerospikePIDs.size(); k++) {
if (aerospikePIDs.get(j)==aerospikePIDs.get(k)) {
duplicates.add(aerospikePIDs.get(k));
System.out.println("duplicate elements for term " +searchTerm+duplicates);
}
}
}
Note: the flag is not necessary, because if you addeda duplicate you can print it directly in the if, without defining new unnecessary variables and code.

Use higher level abstractions:
Push all list elements into a Map<Integer, Integer> - key is the entry in your PIDs list, value is a counter. The corresponding loop simply checks "key present? yes - increase counter; else, add key with counter 1".
In the end, you can iterate that map, and each entry that has a counter > 1 ... has duplicates in your list; and you even get the number of duplicates for free.
And questions/answers that show you nice ways to do such things ... are posted here on almost daily basis. You can start here for example; and you only need to adapt from "String" key to "Integer" key.
Really: when working with collections, your first step is always: find the most highlevel way of getting things done - instead of sitting down and writing such error-prone low-level code as you just did.

You are iterating using the same arraylist. You are checking every data in inner for loop, for sure it will display duplicates.

Related

How to get indexOf element which isn't the first [duplicate]

This question already has answers here:
Trying to find all occurrences of an object in Arraylist, in java
(6 answers)
Closed 3 years ago.
Assumed
ArrayList<Integer> list = Arrays.asList(new Integer[] {1,2,3,4,5,6,1,8,9});
Find second occurence
I want to get the index of the second finding of the (multiple) contained element "1" but list.indexOf(1) will always return 0 (as it's the first finding).
Performance
I want to do this without using loops like for or while.
Since I need it for a game, using loops wouldn't be efficient at all.
EDIT: Is there any way to get "indexOf" some element without iterator ?
You cannot do this without iterating.
indexOf iterates, for example.
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
Same is valid for lastIndexOf.
As you can see no Iterator<Integer> is used at all, if that is what worries you.
And, btw, this isn't a performance concern.
Do you have arrays with millions of elements? If you have, consider changing data structure type.
If you are very much concerned about performance, use a HashMap<Integer, List<Integer>>. Then if your want n'th occurence of an element m, you can do map.get(m).get(n). Your map contains elements and their corresponding indexes.
Once your map is built, the time complexity for your query would be O(1)
Example:
public static void main(String[] args){
int[] a = {1, 2, 1, 3, 4, 1};
Map<Integer, List<Integer>> map = new HashMap<Integer, List<Integer>>();
for(int i = 0; i < a.length; i++){
if(map.containsKey(a[i])){
map.get(a[i]).add(i);
}else{
map.put(a[i], new ArrayList<Integer>());
map.get(a[i]).add(i);
}
}
// second index of 1. Note that index starts from 0.
System.out.println(map.get(1).get(1));
}
Result:
2
list.subList(list.indexOf(1) + 1, list.size()).indexOf(1)
list.indexOf(1, list.indexOf(1) + 1);
The first parameter 1 being the object to be searched.
The second parameter list.indexOf(1) + 1 being the starting index for the search.

how to iterate over consecutive pairs in arrayList

I want to create a loop that iterates through an ArrayList of objects.
for (int i = 0, k=i+1; k < arr.size(); i++) {
int tprice;
tprice=0;
if (arr.get(i).getID()=arr.get(i+1).getID()) {
tprice = arr.get(i).getPrice() + arr.get(i+1).getPrice();
}
else {
if (tprice!=0) {
System.out.println(tprice);
}
else {
System.out.println(arr.get(i).getDuration());
}
}
}
I want to compare element i to element i+1 of the ArrayList, without creating a nested for loop as I am not interested in all the permutations. (e.g, 1->2 then 2->3, not 1->2 then 1->3)
However, my line of code always causes an error because index k at the end of the loop is referencing an out-of-bounds index (or the equivalent for ArrayList).
Say i have three arrays : i=0 compares to i=1, i=1 compares to i=2, i=2 compares to i=3 but throws back an error since it doesn't exist.
Is there any way to overcome this? It seems silly, but I couldn't find anything about it across the forums.
exemple hardcode:
arr.add(new object(444,24)) // 444 is ID, 24 is Price
arr.add(new object(444,29)) // 444 is ID, 29 is Price
arr.add(new object(121,33)) // ...
wanted outcome :
53
53
33
side-question : if i am dealing with the same ID, i would ideally wish to print only once. Is there anyway to do so?
If you touch the two consequent elements of the array, you have to stop one element before you read the end:
for (int i = 0; i < arrayList.size() - 1; i++) {
// do stuff with arrayList.get(i) and arrayList(i+1)
}
Of course, the arrayList must contain at least two elements otherwise the loop will never be entered since the arrayList.size() - 1 would be equal to 0.
Moreover, you confuse arrays with ArrayList<T>.
List<T> of size list.size() has methods list.add(T t) and list.get(int index).
An array int[] array of size (length) array.length access to items with index array[0].
If all you want to check is the adjacent elements in the array, just start from the index 1 till the end and compare the adjacent: current and previous.
for (int i = 1; i < arr.size(); ++i) {
if (arr.get(i) > arr.get(i-1)) ....
}

Java mapping data from two arrays and insert into third array

I am having difficulty mapping the data in two lists into a third list. My sample data is as follows:
Categorylist ID: 1,2,3,4,5,6,7,8,9,10,42,46,49,50
CurrentMonthByCat ID: 1,2,3,4,5,6,7,8,9,10,42,49,50
(the transaction amount value for CurrentMonthByCat: 92,46,40,180,60,10,1510,200,500,10,234,12)
There is a missing 46 in the currentMonthByCat. I am trying to do it in a way such that if the currentMonthByCat ID does not exist from the categorylist ID, I will insert 0 into the third list rather than getting the transaction amount from CurrentMonthByCat and push it into the third list.
ArrayList<Double> total = new ArrayList<Double>();
for(int i = 0; i < categorylist.size(); i++){
for(int j = 0; j < currentMonthByCat.size(); j++){
if(categorylist.get(i).getCategoryID().equals(currentMonthByCat.get(j).getCategory().getCategoryID())){
Log.d("IIIII", categorylist.get(i).getCategoryID());
Log.d("JJJJJ", currentMonthByCat.get(j).getCategory().getCategoryID());
total.add((double)currentMonthByCat.get(j).getTransactionAmt());
}else{
total.add(0.0);
}
}
}
for(int k = 0; k < total.size(); k++){
Log.d("KKKKK", String.valueOf(total.get(k)));
}
But the printed out result of total list is:
92,0,0,0,0,0,0,0,0,0,0,0,0,0,46,0,0,0...
What I expected is:
92,46,40,180,60,10,1510,200,500,10,0,234,12
I wanted to insert 0 only if the ID in currentMonthByCat does not match the ID in categorylist. For instance, the ID 46 which is the 3rd position from the right.
I realized the reason is because firstly I inserted 92 into third array, then the categorylist ID is still at 1, then it will compare with all the rest in the currentMonthByCat before moving to ID 2. That is why the unnecessary zeros. But I not sure how to actually sort it to achieve what I wanted.
Any ideas?
Thanks in advance.
It's easy one. you can't take a decision of adding zero or value in the total array unless the inner loop finish. so probably you add element existAtIndex and initialize it with -1 and in the loop if you find the element then assign the index to existAtIndex and break the loop or if it's not exist then you add zero. so the code will be something like :
ArrayList<Double> total = new ArrayList<Double>();
int existAtIndex;
for(int i = 0; i < categorylist.size(); i++){
// search for the element index
existAtIndex = -1;
for(int j = 0; j < currentMonthByCat.size(); j++){
if(categorylist.get(i).getCategoryID().equals(currentMonthByCat.get(j).getCategory().getCategoryID())){
existAtIndex = j;
break;
}
}
// add the value in the element index or add zero if the element not exist
if (existAtIndex != -1) {
total.add((double)currentMonthByCat.get(existAtIndex).getTransactionAmt());
}
else {
total.add(0.0);
}
}
for(int k = 0; k < total.size(); k++){
Log.d(String.valueOf(total.get(k)));
}
For better code you could use contains method to check for the item if exist or not in arrayList instead of using the basic loop. Good luck
You have a lot of code for what you are trying to do here. I think the following snippet does what you want in a very readable and maintainable way.
//First of all we are interested in getting a transaction amount for each value in currentMonthByCat
//so loop around using your object (not sure what it's called)
for(CurrentMonth value : currentMonthByCat){
//check if it's present.
//We create a new method here that gets you your category list as a list of integers.
//This is key to making the whole method much more readable.
if(categorylist.getIdsAsList().contains(value.getCategory().getCategoryID())){
//it is so add it
total.add(value.getTransactionAmt());
} else {
//it's not so add a 0
total.add(0.0);
}
}
The getIdsAsList method could look like this:
public List<Integer> getIdsAsList(){
List<Integer> result = new ArrayList<>();
for (CategoryListItem item : categorylist) {
result.add(item.getCategoryId());
}
return result;
}
Put your values into Map<Integer, Double>
Map<Integer, Double> map = new HashMap<Integer, Double>();
for (int i = 0; i < currentMonthByCat.size(); ++i) {
//... categoryId = currentMonthByCat.get(i).categoryId
//... amount = currentMonthByCat.get(i).amount
map.put(categoryId, amount);
}
Then traverse the map using values from Categorylist ID:
// create result arraylist
ArrayList<Double> total = new ArrayList<Double>();
for (int i = 0; i < categorylist.size(); ++i) {
Double amount = map.get(categorylist.get(i));
if (amount == null) {
total.add(0.0);
} else {
total.add(amount);
}
}
The result list total will contain amounts for existing mappings, or zeros for non-existent.
Other way
If it is guaranteed categorylist is sorted and CurrentMonthByCat is sorted
you can then traverse one of the lists while keeping index/cursor to the other list and not iterating the other list from the beginning, but from previously remembered cursor value, resulting in better average performance than n^2

sorting an arraylist of objects using insertion sort

here's my code that uses selection. i need to use a insertion and do not use temporary arrays or arraylist. i need help of how to do a insertion sort.
public static void sortStudents(ArrayList<Student> list)
{//selection sort
Student tempStudent;
int count1;
int count2;
int largest;
for (count1=0; count1<list.size()-1; count1++)
{
largest = 0;
for (count2=largest+1; count2<list.size()-count1; count2++)
{
if ((list.get(largest)).compareTo(list.get(count2)) < 0)
{
largest = count2;
}
}
tempStudent = list.get(list.size()-1-count1);
list.set(list.size()-1-count1, list.get(largest));
list.set(largest, tempStudent);
}
}
}
Both selection sort and insertion sort work quite similarly, by having a "not yet sorted" part of the list, and an "already sorted" part. In the beginning, the first one is the whole list, and the second part an empty list at the start or end. While sorting the "not yet sorted" part shrinks, while the "already sorted" part grows, by one element per iteration.
The difference between selection sort and insertion sort is this:
For selection sort, you search the minimum (or maximum) element of the "not yet sorted" part, remove it there and then add it to the end (or beginning) of the already sorted part.
For insertion sort, you take the next element of the "not yet sorted" part of the list, find it's insertion point in the "already sorted" part and insert it there.
This should be enough to change your selection sort to insertion sort.
You don't define variables outside the loop if it is only used in the loop. Restricting the lifetime of your variables makes it more easy to reason about the code.
public static void sortStudents (ArrayList<Student> list)
{
int largest;
for (int i=0; i < list.size () - 1; i++)
{
largest = 0;
for (int j=largest + 1; j < list.size () - i; j++)
{
if ((list.get (largest)).compareTo (list.get (j)) < 0)
{
largest = j;
}
}
Student tempStudent = list.get (list.size () - 1 - i);
list.set (list.size () - 1 - i, list.get (largest));
list.set (largest, tempStudent);
}
}
A bit more indentation makes your code more readable. Now what's your concrete error - doesn't it compile, throws it an exception or does it produce the wrong result?
Here is something suspicious in the inner loop:
largest = 0;
for (int j=largest + 1; j < list.size () - i; j++)
If you set largest to 0, then j will be initialized to 0 + 1 => 1. I guess you had another intention. Did you mean j = i + 1;?

Finding Duplicate Array Elements

I've been struggling to create a function to essentially find all the indices of duplicate elements in a multi-dimensional array(unsorted), in this case a 5x5 array, and then using the indices found changing the parallel elements in a score array. But only find duplicates within columns and not comparatively to the other columns in the array Here is what I've done so far, with research online. The main problem with this code is that it will find all the duplicate elements but not the originals. For example: if the array holds the elements:
{{"a","a","a"},{"b","b","b"},{"a","c","a"}}, then it should change the parallel score array to: {{0,1,0},{1,1,1},{0,1,0}}. But instead it only recognizes the last row and top the top row's duplicates.
Code:
public static void findDuplicates(String a[][])
{
System.out.println("*Duplicates*");
Set set = new HashSet();
for(int j = 0; j<a.length; j++)
{
for(int i=0; i < a[0].length; i++)
{
if(!set.contains(a[i][j]))
{
set.add(a[i][j]);
}
else
{
System.out.println("Duplicate string found at index " + i + "," + j);
scores[i][j] -= scores[i][j];
}
}
set = new HashSet();
}
}
I know my explanation is a bit complicated, but hopefully it is understandable enough. Thanks,
Jake.
Your logic is incorrect. Your outer loop is j and inner loop is i but you're doing:
set.add(a[i][j]);
It should be the other way around:
set.add(a[j][i]);
Technically you could get an out of bounds exception if the array isn't NxN. But you can state that as a precondition.
For some reason you're also setting to 0 with:
scores[i][j] -= scores[i][j];
Why not just:
scores[i][j] = 0;
But to find duplicates within columns:
public static void findDuplicates(String a[][]) {
for (int col=0; col<a[0].length; col++) {
Map<String, Integer> values = new HashMap<String, Integer>();
for (int row=0; row<a.length; row++) {
Integer current = values.put(a[row][col], row);
if (current != null) {
scores[row][col] = 0;
scores[current][col] = 0;
}
}
}
}
How does this work?
I've renamed the loop variables to row and col. There's no reason to use i and j when row and col are far more descriptive;
Like you I assume the input array is correct as a precondition. It can be NxM (rather than just NxN) however;
I use a Map to store the index of each value. Map.put() returns the old value if key is already in the Map. If that's the case you've found a duplicate;
The current (row,col) and (current,col) are set to 0. Why subtract the score from itself rather than simply setting to 0?
if the value "a" is found 3+ times in a column then scores[current][col] will be set to 0 more than once, which is unnecessary but not harmful and makes for simpler code.
I've declared the Map using generics. This is useful and advisable. It says the Map has String keys and Integer values, which saves some casting;
It also uses auto-boxing and auto-unboxing to convert an int (the loop variable) to and from the wrapper class Integer.

Categories

Resources