ClassCastException when calling TreeSet <Long> .contains (Long.valueOf (someLongValue))

I'm at a dead end. I declare my set as follows:

private Set<Long> applicationIds; 

Then I fill it as follows:

 public void setApplicationIds( Set<Long> applicationIds ) { this.applicationIds = new TreeSet<Long>( applicationIds ); this.applications = null; } 

Then I try to use it:

 public List<Application> getApplications() { if ( applications == null ) { applications = new ArrayList<Application>(); if ( applicationIds != null ) { for ( Application application : availableApplications ) { if ( applicationIds.contains( Long.valueOf( application.getId() ) ) ) { applications.add( application ); } } } } return applications; } 

And I get the following:

 java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Long at java.lang.Long.compareTo(Long.java:50) at java.util.TreeMap.getEntry(TreeMap.java:346) at java.util.TreeMap.containsKey(TreeMap.java:227) at java.util.TreeSet.contains(TreeSet.java:234) at org.mitre.asias.pf.pnp.viewmodel.Subscription.getApplications(Subscription.java:84) 

The line that throws the exception (line 84 from the stack trace) is this:

  if ( applicationIds.contains( Long.valueOf( application.getId() ) ) ) { 

Maybe something is missing me, but if the declaration is Set<Long> and I call the contains method, passing in the value Long.valueOf , how can I get this exception?

This is the bean model for the JSF application. I am using Java 6, Tomcat 6.0.32, mojarra 2.1.14, but none of this should make much difference, as generators should prevent such a compilation of the problem ...

-------------- EDIT -----------------

Actually JSF ... I combined a super simplified example with this installer:

 public void setSelectedValues(Set<Long> selectedValues) { this.selectedValues = selectedValues; if (logger.isTraceEnabled()) { StringBuilder message = new StringBuilder("Selected values:"); for (Object value : selectedValues) { message.append("\n\t'").append(value.getClass().getName()) .append("': '").append(value.toString()).append("'"); } logger.trace(message.toString()); } this.selections = null; } 

associated with this component:

 <p:selectManyCheckbox id="numbers" value="#{controller.selectedValues}" layout="pageDirection"> <f:selectItems value="#{controller.availableValues}" /> </p:selectManyCheckbox> 

which writes this to the log:

 15:45:16.887 [http-bio-8080-exec-9] TRACE com.pastdev.learn.debug.Controller - Selected values: 'java.lang.String': '1' 'java.lang.String': '5' 

So, the simple answer is correct (thanks @PaulTomblin for emphasizing this). The setter receives a call with Set , which contains String s. So what is the best conversion process? Do I need to iterate over a list, throwing every value in Long?

As a side note, I tested this on Tomcat 7 using Java 7 and the ClassCastException is gone, however the contains method always returns false , as you would expect.

-------------- EDIT 2 -----------------

I found an answer with the correct way to bind my component here .

-------------- EDIT 3 -----------------

And here is the best explanation for the problem.

0
source share
2 answers

Maybe something is missing for me, but if the declaration is set, and I call the contains method, passing the value Long.valueOf, how can I get this exception?

Note that in Java, generic annotations are just hints for the compiler and do not affect runtime, so you can violate these restrictions at runtime (but somewhere there will be a warning about the compiler).

It looks like your Set<Long> contains at least one line. Where does this kit come from?

since it is assumed that Generics prevents such a compilation time problem

Yes, there should be a warning in your code that there are no generic types or uncontrolled drops. This is just a warning because generics are optional. In the places where you used them, that would be a mistake.

+5
source

OK @ Lucas I just tried using a quick and dirty code using the code you posted as part of the question and it works great. You might need to check your Application class again.

 package javaapplication2; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.TreeSet; public class JavaApplication2 { private static Set<Long> applicationIds; private List<Application> applications; private static final List<Application> availableApplications = new ArrayList<>(); public static void main(String[] args) { JavaApplication2 proj = new JavaApplication2(); for (int i = 1; i <= 11; i++) { Application application = new Application(); application.setId(i); availableApplications.add(application); } Set<Long> applicationIds1 = new TreeSet<>(); applicationIds1.add(11L); applicationIds1.add(12L); applicationIds1.add(13L); proj.setApplicationIds(applicationIds1); for (Application appl : proj.getApplications()) { System.out.println(appl.getId()); } } public void setApplicationIds(Set<Long> applicationIds) { this.applicationIds = new TreeSet<Long>(applicationIds); this.applications = null; } public List<Application> getApplications() { if (applications == null) { applications = new ArrayList<Application>(); if (applicationIds != null) { for (Application application : availableApplications) { if (applicationIds.contains(Long.valueOf(application.getId()))) { applications.add(application); } } } } return applications; } 

}

and

 package javaapplication2; class Application { private int id; public int getId() { return id; } public void setId(int id) { this.id = id; } } 
0
source

All Articles