Error when adding HashMap values to TreeSet - java

Here is some sample code...I always seem to get a ClassCastException...anybody point out what I am doing wrong?
package com.query;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.junit.Test;
import com.google.common.collect.Sets;
public class ClassCastExceptionTest {
#Test
public void test() {
A<SomeType> a1 = new A<SomeType>(1);
A<SomeType> a2 = new A<SomeType>(2);
A<SomeType> a3 = new A<SomeType>(3);
Map<String, A<SomeType>> map = new HashMap<String, A<SomeType>>();
map.put("A1", a1);
map.put("A2", a2);
map.put("A3", a3);
Collection<A<SomeType>> coll = map.values();
Set<A<SomeType>> set = Sets.newTreeSet(coll);
System.out.println("Done.");
//EXCEPTION...
//com.query.ClassCastExceptionTest$A cannot be cast to
//com.query.ClassCastExceptionTest$BaseType
}
private class A<T extends BaseType> extends Base<T> {
public A(int i) {
super(i);
}
}
private class Base<T extends BaseType> implements Comparable<T> {
private Integer id;
public Base(int id) {
this.id = id;
}
/**
* #return the id
*/
public Integer getId() {
return id;
}
/**
* #param id the id to set
*/
#SuppressWarnings("unused")
public void setId(int id) {
this.id = id;
}
#Override
public int compareTo(T o) {
return getId().compareTo(o.getId());
}
}
private class SomeType extends BaseType {
#Override
public Integer getId() {
return 0;
}
#Override
public int compareTo(BaseType o) {
return this.getId().compareTo(o.getId());
}
}
private abstract class BaseType implements Comparable<BaseType> {
public abstract Integer getId();
}
}

In order to be added to TreeSet (with natural ordering) a class should be comparable with itself:
private class Base<T extends BaseType> implements Comparable<Base> { ... }
whereas in your case Base is comparable with T:
private class Base<T extends BaseType> implements Comparable<T> { ... }

A TreeSet uses the objects compareTo method for sorting. So when adding the second A instance to the TreeSet, A#compareTo is invoked with the other A instance as argument, but as this method is expecting BaseType (or a subclass of BaseType) as argument, a ClassCastException is thrown.

Related

java.util.LinkedHashMap cannot be cast to com.common.pojo.myDataDetails

My java class is throwing some error. In my class i am using this to get my data.
((myDataDetails) Names.get(0)).InputParamNames().add("SomeValue");
But it is throwing error
Here is my Pohjo Class.
package common.pojo;
import java.util.Date;
import java.util.List;
public class myDataDetails
{
private String myID;
private List<String> InputParamNames;
private List InputParamData;
public String getmyID() {
return this.myID;
}
public void setmyID(String myID) {
this.myID = myID;
}
public List<String> getInputParamNames() {
return this.InputParamNames;
}
public void setInputParamNames(List<String> InputParamNames) {
this.InputParamNames = InputParamNames;
}
public List getInputParamData() {
return this.InputParamData;
}
public void setInputParamData(List InputParamData) {
this.InputParamData = InputParamData;
}
}
What should I need to change in pojo to avoid this exception.
Your class 'myDataDetails' needs to extend from LinkedHashMap in order to cast it.
What you have right now is a regular POJO class that is not an instance of LinkedHashMap, so you can't cast it as such.
EDIT: It should look like this
package common.pojo;
import java.util.Date;
import java.util.List;
import java.util.LinkedHashMap;
public class myDataDetails extends LinkedHashMap<Object, Object>
{
private String myID;
private List<String> InputParamNames;
private List InputParamData;
public String getmyID() {
return this.myID;
}
public void setmyID(String myID) {
this.myID = myID;
}
public List<String> getInputParamNames() {
return this.InputParamNames;
}
public void setInputParamNames(List<String> InputParamNames) {
this.InputParamNames = InputParamNames;
}
public List getInputParamData() {
return this.InputParamData;
}
public void setInputParamData(List InputParamData) {
this.InputParamData = InputParamData;
}
}

Extend a generic holder class, have it accept only specific objects?

I am trying to understand and accomplish the task of trying to create a class that extends a generic class that accepts all types of classes. So far I have that working. I am trying to create a class that extends a generic holder class and have this class accept only specific objects.
Example, a class called "ComputerOrder" that will not accept an Apple or Orange object but only a ComputerPart or Peripheral object, such as Motherboard or Printer objects. Been stuck on this for 2 weeks. I can't for the life of me figure this concept out. Any help would be appreciated.
abstract class Product{
protected float price;
abstract float price();
public String toString() {
return "Price = " + String.valueOf(price) + " ";
}
}
class Apple extends Product{}
class Orange extends Product{}
class ComputerPart extends Product{
public ComputerPart(float p){
price = p;
}
public float price() {
return price;
}
}
class Motherboard extends ComputerPart{
protected String manufacturer;
public Motherboard(String mfg, float p) {
super(p);
manufacturer = mfg;
}
public String getManufacturer() {
return manufacturer;
}
}
class Peripheral extends Product{
public Peripheral(float p) {
price = p;
}
public float price() {
return price;
}
}
class Printer extends Peripheral{
protected String model;
public Printer(String model, float p) {
super(p);
this.model = model;
}
public String getModel() {
return model;
}
}
class Cheese extends Product{
public Cheese(float p) {
price = p;
}
public float price() {
return price;
}
}
class Cheddar extends Cheese{
public Cheddar(float p) {
super(p);
}
}
class GenericOrder<T>{
public ArrayList<T> storage = new ArrayList<T>();
private static int counter = 1;
public final int id;
public T obj;
public GenericOrder(){
id = counter;
counter++;
}
public void add(T item){
storage.add(item);
}
public T get(int in){
return obj;
}
public void getId(){
System.out.println(this.id);
}
public String toString(){
String ret = "";
Iterator<T> it = storage.iterator();
while (it.hasNext()) {
ret += it.next() + "\n";
}
return ret;
}
}
class ComputerOrder extends GenericOrder {
public void add(ComputerPart in){
if(in instanceof ComputerPart){
storage.add(in);
}
}
}
public class Tme2{
public static void main(String[] args){
ComputerOrder com = new ComputerOrder();
com.add(new Motherboard("bla", 3.33f))
}
}
You can do it like this:
class ComputerOrder<T extends ComputerProduct> extends GenericOrder<T> {
//...
}
Here, ComputerProduct is a class that extends Product and all your computer products like ComputerPart or Peripheral extend ComputerProduct. Similarly, you could create a class FoodProduct derived from Product, from which Apple, Orange and Cheese are derived:
class FoodOrder<T extends FoodProduct> extends GenericOrder<T> {
//...
}
The declaration <T extends ComputerProduct> is a type restriction, which ensures that all types of T are derived from ComputerPart, otherwise you will get a compiler error.
The ComputerOrder class is still generic, so you could instance an order for all computer products:
ComputerOrder order = new ComputerOrder<ComputerProduct>();
// Add peripherals, printers, motherboards...
// Apples, ... will throw compiler errors...
But you could also restrict it to peripherals only:
ComputerOrder order = new ComputerOrder<Peripheral>();
// Add peripherals, printers,...
// Apples, motherboards (ComputerProduct, but NOT Peripheral) will fail...

How to create encoder for custom Java objects?

I am using following class to create bean from Spark Encoders
Class OuterClass implements Serializable {
int id;
ArrayList<InnerClass> listofInner;
public int getId() {
return id;
}
public void setId (int num) {
this.id = num;
}
public ArrayList<InnerClass> getListofInner() {
return listofInner;
}
public void setListofInner(ArrayList<InnerClass> list) {
this.listofInner = list;
}
}
public static class InnerClass implements Serializable {
String streetno;
public void setStreetno(String streetno) {
this.streetno= streetno;
}
public String getStreetno() {
return streetno;
}
}
Encoder<OuterClass> outerClassEncoder = Encoders.bean(OuterClass.class);
Dataset<OuterClass> ds = spark.createDataset(Collections.singeltonList(outerclassList), outerClassEncoder)
And I am getting the following error
Exception in thread "main" java.lang.UnsupportedOperationException: Cannot infer type for class OuterClass$InnerClass because it is not bean-compliant
How can I implement this type of use case for Spark in Java? This worked fine if I remove the inner class. But I need to have an inner class for my use case.
Your JavaBean class should have a public no-argument constructor, getter and setters and it should implement Serializable interface. Spark SQL works on valid JavaBean class.
EDIT : Adding working sample with inner class
OuterInnerDF.java
package com.abaghel.examples;
import java.util.ArrayList;
import java.util.Collections;
import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.Encoder;
import org.apache.spark.sql.Encoders;
import org.apache.spark.sql.SparkSession;
import com.abaghel.examples.OuterClass.InnerClass;
public class OuterInnerDF {
public static void main(String[] args) {
SparkSession spark = SparkSession
.builder()
.appName("OuterInnerDF")
.config("spark.sql.warehouse.dir", "/file:C:/temp")
.master("local[2]")
.getOrCreate();
System.out.println("====> Create DataFrame");
//Outer
OuterClass us = new OuterClass();
us.setId(111);
//Inner
OuterClass.InnerClass ic = new OuterClass.InnerClass();
ic.setStreetno("My Street");
//list
ArrayList<InnerClass> ar = new ArrayList<InnerClass>();
ar.add(ic);
us.setListofInner(ar);
//DF
Encoder<OuterClass> outerClassEncoder = Encoders.bean(OuterClass.class);
Dataset<OuterClass> ds = spark.createDataset(Collections.singletonList(us), outerClassEncoder);
ds.show();
}
}
OuterClass.java
package com.abaghel.examples;
import java.io.Serializable;
import java.util.ArrayList;
public class OuterClass implements Serializable {
int id;
ArrayList<InnerClass> listofInner;
public int getId() {
return id;
}
public void setId(int num) {
this.id = num;
}
public ArrayList<InnerClass> getListofInner() {
return listofInner;
}
public void setListofInner(ArrayList<InnerClass> list) {
this.listofInner = list;
}
public static class InnerClass implements Serializable {
String streetno;
public void setStreetno(String streetno) {
this.streetno = streetno;
}
public String getStreetno() {
return streetno;
}
}
}
Console Output
====> Create DataFrame
16/08/28 18:02:55 INFO CodeGenerator: Code generated in 32.516369 ms
+---+-------------+
| id| listofInner|
+---+-------------+
|111|[[My Street]]|
+---+-------------+

Overriding method with Generics

I have a base class called GenericOrder that can be used to create an order with any type of products, then I have subclasses of that order that are more specific. My problem is with my ComputerOrder class and a method that I'm overriding. Here's the base class code.
import java.util.List;
import java.util.ArrayList;
public class GenericOrder<T> {
private long orderNumber;
private List<T> products;
private T theClass;
public GenericOrder()
{
products = new ArrayList<T>();
orderNumber = System.currentTimeMillis();
}
public long getOrderNumber() {
return orderNumber;
}
public void addProduct(T newProduct) {
products.add(newProduct);
}
public int getNumberOfProducts() {
return products.size();
}
public List<T> getProducts()
{
return products;
}
public void setProducts(List<T> products)
{
this.products = products;
}
public T get()
{
return theClass;
}
public void set(T theClass)
{
this.theClass = theClass;
}
}
And here is my subClass code. The getProducts is the method I'm having trouble with.
import java.util.ArrayList;
import java.util.List;
public class ComputerOrder<T> extends GenericOrder<T> {
private List<ComputerPart> computerParts = new ArrayList<ComputerPart>();
private String orderType = "Computer Parts";
public ComputerOrder() {
super();
}
public void addProduct(ComputerPart newProduct) {
computerParts.add(newProduct);
}
public String getOrderType() {
return orderType;
}
public int getNumberOfProducts() {
return computerParts.size();
}
public List<T> getProducts()
{
return computerParts;
}
}
The Error I get says cannot convert from List(ComputerPart) to List<T>
The error is pretty clear: getProducts() is declared to return a List<T> yet you're returning a List<ComputerPart>. I think we agree that these two are not equivalent.
Looking at your code it looks like that you actually don't want a generic class since ComputerOrder only accepts ComputerParts. What you want is something like the following:
public class ComputerOrder extends GenericOrder<ComputerPart> {
#Override
public List<ComputerPart> getProducts() {
return computerParts;
}
}
Design wise, I think you should reconsider whether products should be in the GenericOrder class. If GenericOrder is meant only to handle the orders, then it might not make sense to have any product related methods or fields defined there. As it is now you have a products List array in GenericOrder that is not being used because you have defined computerParts List array in ComputerOrder. This makes for bad code. In this case your classes would look like:
public class GenericOrder<T> {
private long orderNumber;
private String orderType;
private T theClass;
public GenericOrder(String orderType) {
this.orderType = orderType;
orderNumber = System.currentTimeMillis();
}
public String getOrderType() {
return orderType;
}
public long getOrderNumber() {
return orderNumber;
}
public T get() {
return theClass;
}
public void set(T theClass) {
this.theClass = theClass;
}
}
and
import java.util.ArrayList;
import java.util.List;
public class PartOrder<T> extends GenericOrder<T> {
private List<T> parts = new ArrayList<T>();
public PartOrder(String orderType) {
super(orderType);
}
public void addProduct(T newProduct) {
parts.add(newProduct);
}
public int getNumberOfProducts() {
return parts.size();
}
public List<T> getProducts() {
return parts;
}
}
and you would have a ComputerPartOrder class like so:
public class ComputerPartOrder extends PartOrder<ComputerPart> {
public ComputerPartOrder() {
super("Computer Parts");
}
}
Otherwise, you might also define the GenericOrder.getProducts method as abstract as per this stackoverflow post.
It actually looks like you don't want your ComputerOrder to be generic.
While a GenericOrder<T> is generic and can be an order of anything, ComputerOrder seems specific to ComputerPart(s) and should extend GenericOrder<ComputerPart>.
This way you will only have to implement List<ComputerPart> getProducts() and your code will be fine.
As your ComputerOrders class looks more specific, consider refactoring your code as below :
public class ComputerOrder extends GenericOrder<ComputerPart> {
#Override
public List<ComputerPart> getProducts() { return computerParts; }
}

generic (non-static) method with Class parameter for typesafety, how does it work?

this is my code, Control is an swt-ui-widget, the method find should return a component with the type passed in "clazz". I know how to do this with static methods, but it doesn't work if it's an instance method.
package org.uilib.swt.templating;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Control;
public class Component<T extends Control> {
public final String name;
public final T control;
public Component(String name, T control) {
this.name = name;
this.control = control;
}
public String getName() {
return name;
}
public T getControl() {
return control;
}
public Component<E> find(String query, Class<E extends Control> clazz) {
return null;
}
}
i want to do the following:
Component<Button> x = this.find("asd", Button.class);
As far as I understand, you need the following generic method:
public <E extends Control> Component<E> find(String query, Class<E> clazz) { ... }
public <T extends Component> T find(String query, Class<T> clazz) {
return null;
}

Categories