java TreeSet with custom comparator not working - java

I am trying to get a hang of using custom comparator with TreeSet. However, it seems like something is wrong. I see duplicates no matter whether I use custom equals or the compare from comparator.. Any idea where is the mistake?
Below is the code: (Please look at comments to follow)
import java.util.ArrayList;
import java.util.Comparator;
import java.util.TreeSet;
public class TreemapTest {
public static void main(String[] args) {
//Take an array of integers
int list[] = { 1,2,3,4,2,4,2,5 };
//Create a list of custom objects
ArrayList<Element> elements = new ArrayList<Element>();
//Populate the list with values from int array
for (int v : list){
elements.add(new Element(v));
}
/** Attempt to create a treeset from the arraylist */
// Create the Treeset with custom comparator
TreeSet<Element> nt = new TreeSet<Element>(new Comparator<Element>(){
public int compare(Element a, Element b){
System.out.println("Comparing "+ a.val + " and "+ b.val);
if ( a.val == b.val )
return 0;
if ( (a.val - b.val) > 0 )
return 1;
return -1;
}
});
// Add the elements into the treeset
for (Element elem: elements ){
nt.add(elem);
}
// Output shall not contain duplicates
for (Element elem: elements ){
System.out.print(":"+elem.val);
}
}
}
class Element {
public int val;
Element(int v){
val = v;
}
// boolean equals(Element e){
// return this.val == e.val;
//
// }
}

You are printing the elements list again, change it to nt set.
// Output shall not contain duplicates
for (Element elem: nt){
System.out.print(":"+elem.val);
}

Related

Problems while iterating over an ArrayList of ArrayLists

I'm trying to iterate over an ArrayList of ArrayLists - but somehow everything fails on me and I don't understand the error message.
The error is:
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.util.ArrayList
I've tried using a regular for(int i; i < lists.length; i++) but get the same error. All I want to do is check if any of the ArrayLists in "lists" contains the integer "v".
public static boolean listsContains(ArrayList<ArrayList<Integer>> lists, int v) {
boolean b = false;
for (ArrayList<Integer> list : lists) {
if (list.contains(v)) {
b = true;
} else {
b = false;
}
}
return b;
}
The actual line that causes the error is the "for (ArrayList list"...
Edited: For clarity I edited in the code with more declarative generics (which works just as little as the first code I posted unfortunately).
Edit2: Ok so it's somehow not the method itself that causes the problem so upon request here's the rest of the code that populates these lists. The code is not done but I got caught with this problem while finishing it.
public static void main(String[] args) {
Graph g = DataSource.load();
ArrayList<ArrayList<Integer>> lists = new ArrayList<ArrayList<Integer>>();
for(int i = 0; i < g.numberOfVertices(); i++) {
if(!(listsContains(lists, i))) { // add list if node is unlisted (since after first iteration one entire network is found)
listsCreate(lists, i);
}
Iterator it = g.adj(i).iterator(); // create iterator for current node's edges
if (!(it.hasNext())) { // node has no edges
listsCreate(lists, i);
} else { // node has edges, iterate through them
while(it.hasNext()) {
Edge current = (Edge) it.next();
if(!(listsContains(lists, current.to))) { // unlisted node
int index = listsIndexOf(lists, current.from);
findNetwork(g, lists.get(index), current.to);
} else {
continue; // node already listed
}
}
}
}
System.out.println("Number of connected graphs: " + lists.size());
} // Main
You did not specify the inner ArrayList's components' type. And from your log I can tell that it contains Integers:
public static boolean listsContains(ArrayList<ArrayList<Integer>> lists, int v) {
for (ArrayList<Integer> list : lists) {
if (list.contains(v))
return true;
}
return false; // No inner arrayList contains 'v'
}
EDIT:
or using Java 8 :
public static boolean listsContains(ArrayList<ArrayList<Integer>> lists, int v) {
return lists.stream().anyMatch(list -> list.contains(v));
}
Because you test:
list.contains(v)
list is of type ArrayList without inside type
v is int
replace your ArrayList by ArrayList< Integer >

Double for loop with arrylist that are changing size

The situation is that I have two nested for loops that are each iterating through an arraylist of objects. The outer for loop grabs the object at the current index and adds it two another arraylist called tempCurrEmp. The inner for loop is then suppose to go through and remove all objects in the original arraylist that are the same at a specific field. The problem is that it is not removing all copies and I do not know why. I am assuming it has something to do with the indexes changing after I call remove but I can be sure. Any suggestions are greatly appreciated.
for(int i=0;i<tempAllEmp.size();i++){
tempCurrEmp.add(tempAllEmp.get(i));
tempEmp = tempAllEmp.get(i);
Log.d("LOOP", "Curr emp is: " + tempAllEmp.get(i).getEmployee());
for(int j=i+1;j<tempAllEmp.size();j++){
Log.d("LOOP", "Comparing:" + tempEmp.getEmployee() + " and " + tempAllEmp.get(j).getEmployee().trim());
if(tempAllEmp.get(j).getEmployee().trim().equals(tempEmp.getEmployee())){
Log.d("LOOP", "They were equal");
tempCurrEmp.add(tempAllEmp.get(j));
tempAllEmp.remove(j);
}
}
maxPunch.add(getMaxPunch(tempCurrEmp));
tempCurrEmp.clear();
}
ArrayList public E remove(int index)
Removes the element at the specified
position in this list. Shifts any subsequent elements to the left
(subtracts one from their indices).
So you must substract 1 to your j after removing
tempAllEmp.remove(j--);
And fix the compare:
if(tempAllEmp.get(j).getEmployee().equals(tempEmp.getEmployee())){
Did you forget to trim the tempEmp.getEmployee() as well when comparing to tempAllEmp.get(j).getEmployee().trim() ?
All in all, you have just took one list and put it to another one, becuase:
//You find 2 same employes
tempCurrEmp.add(tempAllEmp.get(i));
tempEmp = tempAllEmp.get(i);
// then you try to figure out if the Employ that you just find from temAllEmp REALLY REALLY exists in the tempAllEmp
for(int j=i+1;j<tempAllEmp.size();j++){
if(tempAllEmp.get(j).getEmployee().trim().equals(tempEmp.getEmployee())){ tempCurrEmp.add(tempAllEmp.get(j));
tempAllEmp.remove(j);
}
// and if you find one, then you first add him to the current employes list and then you remove him from last All employes list, I am supprised that this did not end in an exception
tempCurrEmp.add(tempAllEmp.get(j));
tempAllEmp.remove(j);
====================================================
Try this:
List<Employee> currentEmployees = new ArrayList<Employee>();
for(int i=0 ; i <= tempAllEmp.size() ; i++ ){
if(! currentEmployess.contains(templAllEmp.get(i))){
currentEmployees.add(templAllEmp.get(i));
}
}
plus have your equals() method in Employee class something like this:
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof Employee)) {
return false;
}
Employee other = (Employee) obj;
return this.employeeId.equals(other.employeeId);
}
You should definitely change your algorithm and use Set. See below example:
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
public class Program {
public static void main(String args[]) throws IOException {
List<Node> nodes = new ArrayList<>();
// generate data
Random random = new Random();
while (nodes.size() < 100) {
Node node = new Node();
node.employee = String.valueOf(random.nextInt(10) + 1);
nodes.add(node);
}
System.out.println(nodes);
// remove duplicates
List<Node> newNodes = getUiniqueCollection(nodes);
System.out.println(newNodes);
}
private static List<Node> getUiniqueCollection(List<Node> nodes) {
List<Node> resultNodes = new ArrayList<>();
Set<String> employees = new HashSet<>();
for (Node node : nodes) {
String employee = node.employee.trim();
if (!employees.contains(employee)) {
employees.add(employee);
resultNodes.add(node);
}
}
return resultNodes;
}
}
class Node {
String employee;
#Override
public String toString() {
return employee;
}
}

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);
}
}
}

Logical Error in finding subsets

I'm trying to generalize the code to find all subsets of a given string(elements that are repeated will be treated as distinct) into one that would work for any list.
public class Subsets{
private static <T> void RecursiveSubsets(List<List<T>> list, ArrayList<T> soFar, List<T> rest)
{
if(rest.isEmpty())
{
list.add(soFar);
}
else
{
List<T> remaining;
if(rest.size() == 1)
{
remaining = new ArrayList<T>();
}
else
{
remaining = rest.subList(1, rest.size() - 1);
}
//include the element
ArrayList<T> includeFirst = new ArrayList<T>(soFar);
includeFirst.add(rest.get(0));
RecursiveSubsets(list, includeFirst, remaining);
//exclude the element
RecursiveSubsets(list, soFar, remaining);
}
}
public static <T> List<List<T>> getAllSubsets(List<T> set)
{
List<List<T>> subsets = new ArrayList<List<T>>();
RecursiveSubsets(subsets,new ArrayList<T>(),set);
return subsets;
}
public static void main(String [] args)
{
List<Integer> ints = new ArrayList<Integer>(){
{
add(0);add(1);add(2);add(3);
}
};
List<List<Integer>> allSubsets = getAllSubsets(ints);
System.out.println("Total Subsets returned : " + allSubsets.size());
for(int i=0; i<allSubsets.size(); ++i)
{
for(int j=0; j<allSubsets.get(i).size(); ++j)
{
System.out.print(allSubsets.get(i).get(j) + " ");
}
System.out.println();
}
}
}
After a few attempts I was able to get this to compile but this is what I get as output.
Even if I have more integers, it still returns this. I'm not able to figure out what I have missed and need help finding it.
$ java Subsets
Total Subsets returned : 4
0 1
0
1
Your program is actually almost correct, and you just have the sublist logic a bit wrong.
The javadoc for List.sublist says
Returns a view of the portion of this list between the specified fromIndex, inclusive, and toIndex, exclusive.
The word "exclusive" here is critical.
If you just change
remaining = rest.subList(1, rest.size() - 1);
to
remaining = rest.subList(1, rest.size());
your code works.
The logic of this (in pseudocode) is typically:
List<List<T>> subsets( List<T> list ){
if( list is empty ) return a list containing the empty list;
// else:
subsetsWithout = subsets( list w/o 0th element );
result.addAll(subsetsWithout);
for( subset in subsetsWithout )
result.add( subset + list[0] )
return result;
}
It looks like what you're doing is different, and the fact that you're trying to return things through the function parameters is making it more confusing.

Sorting a List of LIst by the Value of the sublist

private List<String> subList;
private List<List<String>> records = new ArrayList<List<String>>();
for(....){
subList = new ArrayList<String>();
...populate..
records.add(subList);
}
For example, subList has three Strings - a, b, and c.
I want to sort the records by the value of b in subList.
records at 0 has a list of "10", "20", "30"
records at 1 has a list of "10", "05", "30"
records at 2 has a list of "10", "35", "30"
After the sort, the order of records should be -
records at 0 = records at 1 above
records at 1 = records at 0 above
records at 2 = records at 2 above
What could be a good algorithm for that?
Something like:
Collections.sort(records, new Comparator<List<String>>()
{
public int compare(List<String> o1, List<String> o2)
{
//Simple string comparison here, add more sophisticated logic if needed.
return o1.get(1).compareTo(o2.get(1));
}
})
Though I find hard-coding the positions a little dubious in practice, your opinion may differ.
This is just like sorting a string of characters: given two strings, start at the beginning and compare each character; if there's a difference, the string with the lower value comes first, otherwise, look at the next characters from each string. If the strings are of different lengths, treat the shorter string as if it had a suffix of zeroes.
In this case, the "characters" are integer values, obtained by calling Integer.parseInt(). Additionally, implementing a Comparator for a List<String> would be helpful here. Then the Collections.sort() method can be used.
The comparator might look something like this:
final class MyComparator implements Comparator<List<String>> {
public int compare(List<String> a, List<String> b) {
/* Assume all strings are parseable to values
* in range [0,Integer.MAX_VALUE] */
int len = Math.min(a.size(), b.size());
for (int idx = 0; idx < len; ++idx) {
int va = Integer.parseInt(a.get(idx)), vb = Integer.parseInt(b.get(idx));
if (va != vb)
return va - vb;
}
return va.size() - vb.size();
}
#Override
public boolean equals(Object o) {
return o instanceof MyComparator;
}
#Override
public int hashCode() {
return MyComparator.class.hashCode();
}
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class MyList
{
private List<List<Long>> myList;
public MyList()
{
myList = new ArrayList<List<Long>>();
ArrayList arrayList = null;
for(int i=0;i<3;i++)
{
arrayList = new ArrayList<Long>();
for(int x=0;x<3;x++)
{
arrayList.add((Long)Math.round(Math.random()*10));
}
myList.add(arrayList);
}
}
public static void main(String[] args)
{
MyList newList = new MyList();
newList.printList();
Collections.sort(newList.getMyList(),new Comparator<List<Long>>(){
public int compare(List<Long> o1, List<Long> o2) {
if(o1 != null && o2 !=null)
{
Long var1 = o1.get(0);
Long var2 = o2.get(0);
return var1.compareTo(var2);
}
return 0;
}
});
newList.printList();
}
private void printList() {
for(List<Long> subString : myList)
{
System.out.println("List");
for(Long elements : subString)
{
System.out.println(elements);
}
}
}
public List<List<Long>> getMyList() {
return myList;
}
public void setMyList(List<List<Long>> myList) {
this.myList = myList;
}
}
The Column Comparator allows your to sort on any column within the List. The sort is done using the natural sort order of the data in the column.

Categories

Resources