Getting unique elements of List - java

all I have list containing Duplicate values I want somehow to get only Unique values from it and store it another list or set.So that I can perform some operation on it.
My code:
{
List<Integer[]> list1 = new ArrayList<Integer[]>();
list1.add(new Integer[] { 1,10 });
list1.add(new Integer[] { 1,10 });
list1.add(new Integer[] { 1,10 });
list1.add(new Integer[] { 2,10 });
list1.add(new Integer[] { 1,10 });
list1.add(new Integer[] { 3,10 });
for(int i=0;i<list1.size();i++)
{
System.out.println("I - 0 :"+list1.get(i)[0]+"\t I - 1 :"+list1.get(i)[1]+"\n");
}
Set<Integer[]> uniquelist = new HashSet<Integer[]>(list1);
for(Integer[] number: uniquelist){
System.out.println(number[0]+"\t"+number[1]);
}
}
I want the result {1,10;2,10;3,10} to be in separate list.When i googled I got to know for unique we should use set as in Set<Integer[]> uniquelist = new HashSet<Integer[]>(list1); But after doing this I dont know how to access each elements Thanks in advance
Output:
1 10
2 10
1 10
3 10
1 10
1 10

You won't get the result you want using the normal Set approach. As your List contains Integer[], and then won't be considered unique by default. All the array objects are distinct. So, your Set will contain the same elements as your list. However, you can define your Custom Comparator, and use it with a TreeSet constructor.
Another way of doing it can be, define a method contains(List<Integer[]> list, Integer[] value), which checks whether your list contains that array. Define a list named uniqueList. Now, iterate over your original list, and then for each value, call contains method passing uniqueList and that value, as parameters.
Here's how your contains method would look like: -
public static boolean contains(List<Integer[]> list, Integer[] value) {
for (Integer[] arr: list) {
// We can compare two arrays using `Arrays.equals` method.
if (Arrays.equals(arr, value)) {
return true;
}
}
return false;
}
So, you can see that, checking for containment is not the same as, how it would look for just Integer.
Now, from your main method, use this code: -
List<Integer[]> unique = new ArrayList<Integer[]>();
for (Integer[] arr: list1) {
// Use your method here, to test whether this value - `arr`
// is already in `unique` List or not. If not, then add it.
if (!contains(unique, arr)) {
unique.add(arr);
}
}
for (Integer[] arr: unique) {
System.out.println(arr);
}

I would rather use a Set implementation in this case. Use LinkedHashSet if you want your elements to be ordered.
You could declare a class IntegerPair to hold your pairs:
class IntegerPair {
private int key;
private int value;
public IntegerPair(int k, int v) {
key = k;
value = v;
}
public int getKey() {
return key;
}
public int getValue() {
return value;
}
public int hashCode() {
return key * value;
}
public boolean equals(Object o) {
if (!(o instanceof IntegerPair)) {
return false;
}
IntegerPair other = (IntegerPair) o;
return key == other.key && value == other.value;
}
}
Declare it this way:
Set<IntegerPair> set = new LinkedHashSet<IntegerPair>();
Instead of putting new Integer[] values, just do set.add(new IntegerPair(1, 10));
You can loop through your elements using the foreach approach:
for (IntegerPair value : set) {
System.out.println(value.getKey() + " = " + value.getValue());
}

You can access elements by Iterator or by using for each loop
for(Integer number: setOfNumbers){
System.out.println(number);
}

Put them into set using your custom comparator like following:
new TreeSet(list1, new Comparator<Integer[]>() {
public int compare(Integer[] one, Integer[] two) {
int n = one.length;
for (int i = 0; i < n; i++) {
int comp = one.compareTo(two);
if (comp != 0) {
return comp;
}
}
return 0;
}
});
Pay attention that I used TreeSet that can accept custom comparator. It is because you are dealing with arrays. If however you define your own class that holds 2 int values you can make it to implement equals() and hashCode() that allows using any Set implementation.

the Integer[] number in your for loop is an array. to get the values inside you have to use number[index] instruction. to do that you can either do a classic while or for loop using a variable as an index
for(int i=0;i<number.length;i++) {
...
}
or a foreach loop:
for(Integer num : number){
...
}

This may help you...
public static void main(String [] args){
Set<Integer []> set = new TreeSet<Integer []>(new Comparator<Integer[]>(){
public int compare(Integer[] o1, Integer[] o2) {
if(o1.length == o2.length){
for(int i = 0; i < o1.length; i++){
if(o1[i] != o2[i]){
return -1;
}
}
return 0;
}
return -1;
}
});
set.add(new Integer[]{1,2});
set.add(new Integer[]{1,2});
set.add(new Integer[]{1,2});
set.add(new Integer[]{1,3});
int j = 0;
for(Integer[] i: set){
System.out.println("\nElements: "+j);
j++;
for(Integer k : i){
System.out.print(k+" ");
}
}
}
You need to use Comparator to compare two elements of same. As we don't have comparator for Array, Set will use actual object to compare.. using comparator you will have to tell set that this two arrays are same and do not add other same array

Try Table collection in Google-guava.
Example :
Table<Integer, Integer, Integer[]> sampleTable = HashBasedTable.create();
sampleTable.put(1, 10, new Integer[] { 1,10 });
sampleTable.put(2, 10, new Integer[] { 2,10 });
sampleTable.put(1, 10, new Integer[] { 1,10 });
So it will overwrite the duplicate values. Finally you have only unique values.

Related

Why is my Java function returning null?

class Solution {
Map<List<Integer>, Integer> map = new HashMap<>();
List<List<Integer>> ret = new ArrayList<>();//Created An ArrayList
public void dfs(int index, int target, List<Integer> choosen, int[] nums)
{
if(choosen.size()==3 && target==0 && !map.containsKey(choosen)){
ret.add(choosen);
map.put(choosen,0);
for(int j=0;j<list.size();j++)
System.out.print(list.get(j)+" ");
System.out.println();
//map.put(choosen,0);
return;
}
for(int i=index;i<nums.length;i++)
{
int x = nums[i];
choosen.add(x);
target-=x;
dfs(i+1,target,choosen,nums);
target+=nums[i];
choosen.remove(choosen.size()-1);
}
}
public List<List<Integer>> threeSum(int[] nums) {
List<Integer> choosen = new ArrayList<>();
Arrays.sort(nums);
dfs(0,0,choosen,nums);
return ret; //Returning Null
}
}
Why am i not able to add in "ret"? It's returning null.
I just want to add my choosen list into ret when the condition is true and return ret List.
I think the problem is that the if statement is checked before 'choosen' value change (when it is empty).
Try to have the if statement inside the for loop.

Sorting a List - How to?

I have three object classes called Size1, Size2, Size3
All Size classes has different values (all Values are Strings):
Size1.getValue() = "1"
Size2.getValue() = "2"
Size3.getValue() = "1"
I want to sort a List so that it wouldn't contain duplicate values.
Here it is what I tried:
private List<Size> getSortedSizes(List<Size> allSizes){
List<Size> sortedArray = new ArrayList<>();
for (int i = 0; i < allSizes.size(); i++){
Size size = allSizes.get(i);
if (sortedArray.size() == 0){
sortedArray.add(Size);
} else {
for (int a = 0; a < sortedArray.size(); a++) {
if (!sortedArray.get(a).getValue().equals(Size.getValue())) {
sortedArray.add(Size);
}
}
}
}
return sortedArray;
}
Add to a TreeSet, not an Arraylist
TreeSets are ordered and cannot contain duplicates
You could implement your method in the following way:
private Set<Size> getSortedSizes(List<Size> allSizes) {
Set<Size> sorted = new TreeSet<>(sortedArray);
return sorted;
}
But you have to implement two methods in your Size class, they are: hashCode() and int compareTo(Object o) from the Comparable interface

Sort ArrayList items by name

I am trying to rearrange an ArrayList based on the name of the items to be on specific index.
My list currently is this:
"SL"
"TA"
"VP"
"SP"
"PR"
and i want to rearrange them to:
"SL"
"SP"
"TA"
"PR"
"VP"
but based on the name and not in the index.
I have tried this:
for (int i=0; i< list.size(); i++){
if (list.get(i).getCategoryName().equals("SL")){
orderedDummyJSONModelList.add(list.get(i));
}
}
for (int i=0; i< list.size(); i++){
if (list.get(i).getCategoryName().equals("SP")){
orderedDummyJSONModelList.add(list.get(i));
}
}
for (int i=0; i< list.size(); i++){
if (list.get(i).getCategoryName().equals("TA")){
orderedDummyJSONModelList.add(list.get(i));
}
}
for (int i=0; i< list.size(); i++){
if (list.get(i).getCategoryName().equals("PR")){
orderedDummyJSONModelList.add(list.get(i));
}
}
for (int i=0; i< list.size(); i++){
if (list.get(i).getCategoryName().equals("VP")){
orderedDummyJSONModelList.add(list.get(i));
}
}
and it works fine, but i want to know if there is a more efficient way to do in 1 for loop or maybe a function. I do not wish to do it like this:
orderedDummyJSONModelList.add(list.get(0));
orderedDummyJSONModelList.add(list.get(3));
orderedDummyJSONModelList.add(list.get(1));
orderedDummyJSONModelList.add(list.get(4));
orderedDummyJSONModelList.add(list.get(2));
Which also works. Any ideas?
You can use Collection.Sort method as Collection.Sort(list) since list is a List<String> you will be fine. But if you want to implement a new comparator:
Collections.sort(list, new NameComparator());
class NameComparator implements Comparator<String> { //You can use classes
#Override
public int compare(String a, String b) { //You can use classes
return a.compareTo(b);
}
}
EDIT:
You can define a class comparator for your needs:
class ClassComparator implements Comparator<YourClass> { //You can use classes
#Override
public int compare(YourClass a, YourClass b) { //You can use classes
return a.name.compareTo(b.name);
}
}
The key thing here is: you need to get clear on your requirements.
In other words: of course one can shuffle around objects stored within a list. But: probably you want to do that programmatically.
In other words: the correct approach is to use the built-in Collection sorting mechanisms, but with providing a custom Comparator.
Meaning: you better find an algorithm that defines how to come from
"SL"
"TA"
"VP"
"SP"
"PR"
to
"SL"
"SP"
"TA"
"PR"
"VP"
That algorithm should go into your comparator implementation!
The point is: you have some List<X> in the first place. And X objects provide some sort of method to retrieve those strings you are showing here. Thus you have to create a Comparator<X> that works on X values; and uses some mean to get to those string values; and based on that you decide if X1 is <, = or > than some X2 object!
hereĀ“s an answer just specific for your problem working just for the given output. If the List contains anything else this might break your ordering, as there is no rule given on how to order it and the PR just randomly appears in the end.
public static void main(String[] args) {
List<String> justSomeNoRuleOrderingWithARandomPRInside = new ArrayList<String>();
justSomeNoRuleOrderingWithARandomPRInside.add("SL");
justSomeNoRuleOrderingWithARandomPRInside.add("TA");
justSomeNoRuleOrderingWithARandomPRInside.add("VP");
justSomeNoRuleOrderingWithARandomPRInside.add("SP");
justSomeNoRuleOrderingWithARandomPRInside.add("PR");
java.util.Collections.sort(justSomeNoRuleOrderingWithARandomPRInside, new NameComparator());
for(String s : justSomeNoRuleOrderingWithARandomPRInside) {
System.out.println(s);
}
}
static class NameComparator implements Comparator<String> { //You can use classes
#Override
public int compare(String a, String b) { //You can use classes
// Lets just add a T in front to make the VP appear at the end
// after TA, because why not
if (a.equals("PR")) {
a = "T"+a;
} else if(b.equals("PR")) {
b = "T"+b;
}
return a.compareTo(b);
}
}
O/P
SL
SP
TA
PR
VP
But honestly, this solution is crap, and without any clear rule on how to order these this will be doomed to fail as soon as you change anything as #GhostCat tried to explain.
How about this
// define the order
List<String> ORDER = Arrays.asList("SL", "SP", "TA", "PR", "VP");
List<MyObject> list = ...
list.sort((a, b) -> {
// lamba syntax for a Comparator<MyObject>
return Integer.compare(ORDER.indexOf(a.getString()), ORDER.indexOf(b.getString());
});
Note that this will put any strings that aren't defined in the ORDER list at the start of the sorted list. This may or may not be acceptable - it may be worth checking that only valid strings (i.e. members of ORDER) appear as the result of MyObject.getString().
Use a hashmap to store the weight of all strings (Higher the value of the hashmap means the later this string should come in the final list).
Using a Hashmap, so you can expand it later for other strings as well. It'll be easier to enhance in future.
Finally, Use a custom Comparator to do it.
Required Setup:
List<String> listOfStrings = Arrays.asList("SL", "TA", "VP", "SP", "PR");
HashMap<String, Integer> sortOrder = new HashMap<>();
sortOrder.put("SL", 0);
sortOrder.put("TA", 1);
sortOrder.put("VP", 2);
sortOrder.put("SP", 3);
sortOrder.put("PR", 4);
Streams:
List<String> sortedList = listOfStrings.stream().sorted((a, b) -> {
return Integer.compare(sortOrder.get(a), sortOrder.get(b));
}).collect(Collectors.toList());
System.out.println(sortedList);
Non-Stream:
Collections.sort(listOfStrings, (a, b) -> {
return Integer.compare(sortOrder.get(a), sortOrder.get(b));
});
OR
listOfStrings.sort((a, b) -> {
return Integer.compare(sortOrder.get(a), sortOrder.get(b));
});
System.out.println(listOfStrings);
Output:
[SL, TA, VP, SP, PR]
You can build an index map using a LinkedHashMap. This will be used to lookup the order which to sort using the category names of your items.
ItemSorting
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ItemSorting {
public static void main(String[] args) {
List<Item> list = new ArrayList<Item>();
IndexMap indexMap = new IndexMap("SL", "SP", "TA", "PR", "VP");
ItemComparator itemComparator = new ItemComparator(indexMap);
list.add(new Item("SL"));
list.add(new Item("TA"));
list.add(new Item("VP"));
list.add(new Item("SP"));
list.add(new Item("PR"));
Collections.sort(list, itemComparator);
for (Item item : list) {
System.out.println(item);
}
}
}
ItemComparator
import java.util.Comparator;
public class ItemComparator implements Comparator<Item> {
private IndexMap indexMap;
public IndexMap getIndexMap() {
return indexMap;
}
public void setIndexMap(IndexMap indexMap) {
this.indexMap = indexMap;
}
public ItemComparator(IndexMap indexMap) {
this.indexMap = indexMap;
}
#Override
public int compare(Item itemA, Item itemB) {
if (itemB == null) return -1;
if (itemA == null) return 1;
if (itemA.equals(itemB)) return 0;
Integer valA = indexMap.get(itemA.getCategoryName());
Integer valB = indexMap.get(itemB.getCategoryName());
if (valB == null) return -1;
if (valA == null) return 1;
return valA.compareTo(valB);
}
}
IndexMap
import java.util.LinkedHashMap;
public class IndexMap extends LinkedHashMap<String, Integer> {
private static final long serialVersionUID = 7891095847767899453L;
public IndexMap(String... indicies) {
super();
if (indicies != null) {
for (int i = 0; i < indicies.length; i++) {
this.put(indicies[i], new Integer(i));
}
}
}
}
Item
public class Item {
private String categoryName;
public Item(String categoryName) {
super();
this.categoryName = categoryName;
}
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((categoryName == null) ? 0 : categoryName.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
Item other = (Item) obj;
if (categoryName == null) {
if (other.categoryName != null) return false;
} else if (!categoryName.equals(other.categoryName)) return false;
return true;
}
#Override
public String toString() {
return String.format("Item { \"categoryName\" : \"%s\" }", categoryName);
}
}
Result
Item { "categoryName" : "SL" }
Item { "categoryName" : "SP" }
Item { "categoryName" : "TA" }
Item { "categoryName" : "PR" }
Item { "categoryName" : "VP" }
You coud define a helper method like this one:
public static int get(String name) {
switch (name) {
case "SL":
return 1;
case "SP":
return 2;
case "TA":
return 3;
case "PR":
return 4;
case "VP":
return 5;
default:
return 6;
}
}
and write in your main method something like:
ArrayList<String> al = new ArrayList<>();
al.add("SL");
al.add("TA");
al.add("VP");
al.add("SP");
al.add("PR");
Collections.sort(al, (o1, o2) -> return get(o1) - get(o2); );
al.forEach((s) -> System.out.println(s));
You can create a Map that maintains the position. When you iterate through the unordered list just get the position of that string value and insert into new array(not arraylist), then later if required you can convert that array to ArrayList.
Example code:
Map<String,Integer> map = new HashMap<>(); //you can may be loop through and make this map
map.put("SL", 0);
map.put("SP", 1);
map.put("TA",2);
map.put("PR",3);
map.put("VP",3);
List<String> list1 // your unordered list with values in random order
String[] newArr = new String[list1.size()];
for(String strName: list1){
int position = map.get(strName);
arr[position] = strName;
}
//newArr has ordered result.

Split ArrayList in multiple ArrayLists where values are same

Well im stuck on this point.
im trying to make sort function what does this.
parentarraylist = [1,1,1,2,3,2,3,3,2,2,1];
*magic*
childarraylist1 = [1,1,1,1];
childarraylist2 = [2,2,2,2];
childarraylist3 = [3,3,3];
the magic part is where im stuck.
i have tryied putting it in an for loop(the parent) and checking on the value. like this
int i = 0;
int finder = 0;
ArrayList<int> initArray = new ArrayList();
for(int list : parentarraylist){
if(i == 0){
finder = list
}
if(finder == list){
initArray.add(list);
parentarraylist.remove(list);
}else{
new ArrayList *value of list* = new ArrayList();
finder = list;
*value of list*.add(list);
}
}
this results in a view errors like
java.util.ConcurrentModificationException
and i cant set value of list
what can i do to make this work?
This little snippet should help you achieve your goal:
//maps will hold ALL unique integer as it's key
HashMap<Integer, ArrayList<Integer>> maps = new HashMap<Integer, ArrayList<Integer>>();
//your initial array, written inline for clarity
ArrayList<Integer> parentarraylist = new ArrayList<Integer>(Arrays.asList( new Integer[] {1,1,1,2,3,2,3,3,2,2,1}));
//get the iterator so that we won't need another temporary int variable for loop
Iterator<Integer> iterator = parentarraylist.iterator();
while(iterator.hasNext()){
//next = current integer in our array
Integer next = iterator.next();
//check if we have already have current integer or not
if(!maps.containsKey(next)){
//we don't have it, initialise an arraylist for this specific integer
ArrayList<Integer> x = new ArrayList<Integer>();
x.add(next);
//put it to our map holder
maps.put(next, x);
} else {
//already have it, add directly
maps.get(next).add(next);
}
}
This codes will print something like this:
printMap(maps);
//1 = [1, 1, 1, 1]
//2 = [2, 2, 2, 2]
//3 = [3, 3, 3]
printMap() is taken from this answer: Iterate through a HashMap
public static void printMap(Map mp) {
Iterator it = mp.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry)it.next();
System.out.println(pair.getKey() + " = " + pair.getValue());
it.remove(); // avoids a ConcurrentModificationException
}
}
You could try something like this:
public static void main(String[] args) {
ArrayList<Integer> parent = new ArrayList<Integer>();
ArrayList<ArrayList<Integer>> results = new ArrayList<ArrayList<Integer>>();
parent.add(3);
parent.add(1);
parent.add(1);
parent.add(2);
parent.add(3);
parent.add(3);
parent.add(1);
for(int i : parent)
{
boolean check = false;
for(ArrayList<Integer> result : results)
{
if(result.size() > 0)
{
if(result.get(0) == i)
{
check = true;
result.add(i);
break;
}
}
}
if(!check)
{
ArrayList<Integer> temp = new ArrayList<Integer>();
temp.add(i);
results.add(temp);
}
}
for(ArrayList<Integer> i : results)
{
for(int j : i)
{
System.out.print("" + j);
}
System.out.println();
}
}
Output:
333
111
2
The problem is that you remove an element from an array over which you are iterating. The
parentArrayList.remove(list);
causes the error here. If you remove this line your program will work. At the moment I do not see the benefit of removing the item from the parentArrayList for your sorting algorithm so just delete it and you are good to go.

print duplicates in arrayList only one time

i have an arrayList ( named error_dub ) i want to print the duplicates only one time here is my code
for(x=0 ; x<=error_dub.size()-1 ; x++){
for(int h=x+0 ; h<=error_dub.size() ; h++){
if(error_dub.get(x).equals(error_dub.get(h) && x!=h){
System.out.println(error_dub.get(x)+" is duplicated ");
}
}
}
here the line is printed more than once so how can i printed only once ?
Use two sets (this assumes X is the class of your object):
// Returns a set of all duplicates in a list
public Set<X> getDuplicates(final List<X> list)
{
final Set<X> dups = new HashSet<X>();
final Set<X> set = new HashSet<X>();
/*
* Cycle through all elements in the original list. Add it to "set":
*
* - if the .add() method returns true, this is the first time the element is seen;
* - if it returns false, then this is not the first time, it is a duplicate:
* add it to "dups".
*/
for (final X element: list)
if (!set.add(element))
dups.add(element);
return dups;
}
Set's .add() will return false if the set is not modified as a result of the operation, which means if the element was already there.
Copy/paste that function into your existing code and replace the snippet above with:
for (final X dup: getDuplicates(error_dub))
System.out.println(dup + " is duplicated");
Important note: the getDuplicates() function as it is written will NOT respect element order. If order matters to you, replace dups with a LinkedHashSet instead of a HashSet.
you can use .add() method of set to check for duplicates. Method posted below adds list elements to set1. If element is a duplicate (.add() returns true), then element is adde to setToReturn
public Set<Integer> findDuplicates(List<Integer> listContainingDuplicates)
{
final Set<Integer> setToReturn = new HashSet();
final Set<Integer> set1 = new HashSet();
for (Integer yourInt : listContainingDuplicates)
{
if (!set1.add(yourInt))
{
setToReturn.add(yourInt);
}
}
return setToReturn;
}
ArrayList<String> ar=new ArrayList<String>();
ArrayList<String> ar2=new ArrayList<String>();
ar.add("1");
ar.add("2");
ar.add("3");
ar.add("4");
ar.add("5");
ar.add("1");
ar.add("2");
ar.add("1");
for(int x=0;x<ar.size();x++)
{
if(!ar2.contains(ar.get(x)))
{
for(int y=x+1;y<ar.size()-1;y++)
{
if((ar.get(y).equals(ar.get(x))))
{
System.out.print("repeating "+ar.get(x));
ar2.add(ar.get(x));
break;
}
}
}
}
you can do like this.
//method to identify the duplicate elements in array list
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Scanner;
public class Dup
{
public static void main(String[] args)
{
ArrayList<Integer> a=new ArrayList<Integer>();
System.out.println("enter elements");
int g;
Scanner b= new Scanner(System.in);
for(int i=0;i<10;i++)
{
g=b.nextInt();
a.add(g);
}
HashSet<Integer> c=new HashSet<Integer>();
ArrayList<Integer> d=new ArrayList<Integer>();
for (Integer y : a)
{
if (c.contains(y))
{
d.add(y);
}
else
c.add(y);
}
System.out.println("original elements are:"+c);
System.out.println("duplicate elements are:");
for(Integer h:d)
{
System.out.println(h);
}
}
}

Categories

Resources