Stuck in generics - java

I've a base class BaseNewsItem, and 2 derived classes NewsItem and MovieNewsItem. Then, there's a MovieListingFeed class which holds a list of MovieNewsItem and is parcelable. It can parcel this list as and when required by any activity.
protected MovieNewsListingFeed(Parcel in) {
this.pg = in.readParcelable(PageDetail.class.getClassLoader());
this.items=new ArrayList<>();
in.readTypedList(items, MovieNewsItem.CREATOR);
}
I receive an error at the line :
in.readTypedList(items, MovieNewsItem.CREATOR);
Error:
Error:(60, 11) error: method readTypedList in class Parcel cannot be applied to given types; required: List<T>,Creator<T> found: ArrayList<CAP#1>,Creator<CAP#2> reason: inferred type does not conform to equality constraint(s) inferred: CAP#2 equality constraints(s): CAP#2,CAP#1 where T is a type-variable: T extends Object declared in method <T>readTypedList(List<T>,Creator<T>) where CAP#1,CAP#2 are fresh type-variables: CAP#1 extends BaseNewsItem from capture of ? extends BaseNewsItem CAP#2 extends BaseNewsItem from capture of ? extends BaseNewsItem
I'm a novice at Generics, so when I searched for the above error, I didn't completely get the solutions posted. I only added as I needed to convert ArrayList<MovieNewsItem> to ArrayList<BaseNewsItem>.
Relevant code from MovieNewsItem class:
public static final Creator<? extends BaseNewsItem> CREATOR = new Creator<MovieNewsItem>() {
public MovieNewsItem createFromParcel(Parcel source) {
return new MovieNewsItem(source);
}
public MovieNewsItem[] newArray(int size) {
return new MovieNewsItem[size];
}
};
Let me know if any further code snippets are needed.
UPDATE 1: (readTypedList from Android framework.)
public final <T> void readTypedList(List<T> list, Parcelable.Creator<T> c) {
int M = list.size();
int N = readInt();
int i = 0;
for (; i < M && i < N; i++) {
if (readInt() != 0) {
list.set(i, c.createFromParcel(this));
} else {
list.set(i, null);
}
}
for (; i<N; i++) {
if (readInt() != 0) {
list.add(c.createFromParcel(this));
} else {
list.add(null);
}
}
for (; i<M; i++) {
list.remove(N);
}
}
MovieNewsListingFeed.java (Problem file):
public class MovieNewsListingFeed implements Parcelable {
PageDetail pg;
public void setItems(ArrayList<? extends BaseNewsItem> items) {
this.items = items;
}
ArrayList<? extends BaseNewsItem> items;
public ArrayList<? extends BaseNewsItem> getItemsTemp() {
return itemsTemp;
}
public void setItemsTemp(ArrayList<? extends BaseNewsItem> itemsTemp) {
this.itemsTemp = itemsTemp;
}
ArrayList<? extends BaseNewsItem> itemsTemp;
public ArrayList<? extends BaseNewsItem> getItems() {
return items;
}
public PageDetail getPg() {
return pg;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeParcelable(this.pg, flags);
dest.writeTypedList(items);
}
public MovieNewsListingFeed() {
}
protected MovieNewsListingFeed(Parcel in) {
this.pg = in.readParcelable(PageDetail.class.getClassLoader());
this.items = new ArrayList<>();
in.readTypedList(items, MovieNewsItem.CREATOR);
}
public static final Parcelable.Creator<MovieNewsListingFeed> CREATOR = new Parcelable.Creator<MovieNewsListingFeed>() {
public MovieNewsListingFeed createFromParcel(Parcel source) {
return new MovieNewsListingFeed(source);
}
public MovieNewsListingFeed[] newArray(int size) {
return new MovieNewsListingFeed[size];
}
};
}
MovieNewsItem.java:
public class MovieNewsItem extends BaseNewsItem implements Parcelable {
String hl;
String imageid;
String syn;
String id;
String dm;
String tn;
String dl = "";
String sectionHeader;
String upd;
String ud;
private int validListPosition = -1;
public int getValidListPosition() {
return validListPosition;
}
#Override
public void setTitle(String title) {
}
#Override
public void setId(String id) {
}
#Override
public void setDate(String date) {
}
#Override
public void setNewsType(int newsType) {
}
public String getFormatedDate() {
return formatedDate;
}
String formatedDate;
int position;
int newSectionType = NewsType.CONTENT_TYPE_NEWS;
String dayHeading;
public int getPosition() {
return position;
}
public void setPosition(int position) {
this.position = position;
}
public void setNewSectionType(int newSectionType) {
this.newSectionType = newSectionType;
}
public String getDayHeading() {
return dayHeading;
}
public void setDayHeading(String dayHeading) {
this.dayHeading = dayHeading;
}
#Override
public void setValidListPosition(int listPosition) {
}
public String getWu() {
return wu;
}
String wu;
public String getHl() {
return hl;
}
public String getImageid() {
return imageid;
}
public String getSyn() {
return syn;
}
public String getId() {
return id;
}
public String getDm() {
return dm;
}
public String getTn() {
return tn;
}
public String getDl() {
return dl;
}
public String getSectionHeader() {
return sectionHeader;
}
public MovieNewsItem() {
}
#Override
public String getTitle() {
return (!TextUtils.isEmpty(getSyn())) ? getSyn() : getHl();
}
#Override
public String getDate() {
return getFormatedDate();
}
#Override
public int getNewsType() {
return newSectionType;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.hl);
dest.writeString(this.imageid);
dest.writeString(this.syn);
dest.writeString(this.id);
dest.writeString(this.dm);
dest.writeString(this.tn);
dest.writeString(this.dl);
dest.writeString(this.sectionHeader);
dest.writeString(this.upd);
dest.writeString(this.ud);
dest.writeInt(this.position);
dest.writeInt(this.newSectionType);
dest.writeString(this.dayHeading);
dest.writeString(this.wu);
}
protected MovieNewsItem(Parcel in) {
this.hl = in.readString();
this.imageid = in.readString();
this.syn = in.readString();
this.id = in.readString();
this.dm = in.readString();
this.tn = in.readString();
this.dl = in.readString();
this.sectionHeader = in.readString();
this.upd = in.readString();
this.ud = in.readString();
this.position = in.readInt();
this.newSectionType = in.readInt();
this.dayHeading = in.readString();
this.wu = in.readString();
}
public static final Creator<? extends BaseNewsItem> CREATOR = new Creator<MovieNewsItem>() {
public MovieNewsItem createFromParcel(Parcel source) {
return new MovieNewsItem(source);
}
public MovieNewsItem[] newArray(int size) {
return new MovieNewsItem[size];
}
};
#Override
public boolean equals(Object obj) {
MovieNewsItem newsItem = this;
if (obj instanceof MovieNewsItem) {
MovieNewsItem oldNewsItem = (MovieNewsItem) obj;
if (oldNewsItem != null &&
newsItem.id.equals(oldNewsItem.id)) {
return true;
}
}
return false;
}
}
BaseNewsItem.java:
public abstract class BaseNewsItem implements NewsItemType {
}
NewsItemType.java:
public interface NewsItemType extends Parcelable {
String getTitle();
String getId();
String getDate();
int getNewsType();
String getDayHeading();
int getValidListPosition();
int getPosition();
void setTitle(String title);
void setId(String id);
void setDate(String date);
void setNewsType(int newsType);
void setDayHeading(String dayHeading);
void setValidListPosition(int listPosition);
void setPosition(int position);
}

Your issue can be reproduced with this minimal example (replace ? extends Object by ? extends BaseNewsItem and the second list by a Parcelable.Creator and you'll see that the logic is exactly the same):
public void test() {
List<? extends Object> a1 = new ArrayList<> ();
List<? extends Object> a2 = new ArrayList<> ();
m(a1, a2); //your compilation error here
}
public <T> void m(List<T> a1, List<T> a2) { }
The problem is that the generic type of the two lists are unrelated: they both extend the same base class but that's all we know about them - for example a1 may be a List<String> and a2 a List<Integer>.
However the m method expects the two generic types to be the same - which is not what you are passing.
So you need to pass lists which have the same generic type, for example:
public void test() {
List<SomeBaseClass> a1 = new ArrayList<> ();
List<SomeBaseClass> a2 = new ArrayList<> ();
m(a1, a2); //compiles fine
}
public <T> void m(List<T> a1, List<T> a2) { }

This is due to type mis-match
Change
ArrayList<? extends BaseNewsItem> itemsTemp;
to
List<? extends BaseNewsItem> itemsTemp;
Change the method like this:
public final <T> void readTypedList(List<? extends BaseNewsItem> list, Parcelable.Creator<? extends BaseNewsItem> c) {
}
Hope it will work.

Related

Call an object from a map and cast directly

private static final Map<Integer, GameObject> OBJECT = new ConcurrentHashMap<>();
I have a map in which I store GameObjects, which is extended by PlayerObject, NpcObject, ItemObject.
I'm trying to create a method on which I call the object by ID and class type and cast at it directly and if it's not exists or the class of the object ID does not match the given one to return null.
So for example
final PlayerObject object = getObject(<id>, PlayerObject);
Is there any way?
Edit:
I managed to do this:
public <T extends EventObject> T getObject(final int objectId)
{
final EventObject object = OBJECT.get(objectId);
return Objects.nonNull(object) && object.getClass() == ? T (object) : null;
}
But i don't want to use Class<? extends EventObject> in parameter of this method. Can't i somehow check using the generic T if it's the same class to cast it and return or else null?
You can use Class#isInstance to check if the object's type is correct and Class#cast to convert the object to the correct type.
public static <T extends GameObject> T getObject(Integer id, Class<T> clazz) {
GameObject obj = OBJECT.get(id);
if(!clazz.isInstance(obj)) return null;
return clazz.cast(obj);
}
// ...
final PlayerObject object = getObject(<id>, PlayerObject.class);
try this complete generic method:
public static <T> T getObject(int id, Class<T> c){
Object object = OBJECT.get(id);
return object != null && object.getClass() == c ? c.cast(object) : null;
}
The other parts of the program:
private static final Map<Integer, GameObject> OBJECT = new ConcurrentHashMap<>();
public static void main(String[] args) throws ParseException {
init();
PlayerObject p = getObject(3, PlayerObject.class);
ItemObject i = getObject(3, ItemObject.class);
PlayerObject p2 = getObject(4, PlayerObject.class);
System.out.println(p);
System.out.println(i);
System.out.println(p2);
}
private static void init() {
OBJECT.put(1, new PlayerObject(1, "SomePlayer1"));
OBJECT.put(2, new PlayerObject(2, "SomePlayer2"));
OBJECT.put(3, new ItemObject(3, 5));
OBJECT.put(4, new ItemObject(4, 7));
}
GameObject.class
public class GameObject {
protected int id;
GameObject(int id) {
this.id = id;
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
}
PlayerObject.class
public class PlayerObject extends GameObject {
private String playerName;
PlayerObject(int id, String playerName) {
super(id);
this.playerName = playerName;
}
public String getPlayerName() {
return this.playerName;
}
public void setPlayerName(String playerName) {
this.playerName = playerName;
}
#Override
public String toString() {
return "PlayerObject{\"id\": " +
this.id +
", \"playerName\": \"" +
this.playerName +
"\"}";
}
}
ItemObject.class
public class ItemObject extends GameObject {
private int itemCount;
ItemObject(int id, int itemCount) {
super(id);
this.itemCount = itemCount;
}
public int getItemCount() {
return this.itemCount;
}
public void setItemCount(int itemCount) {
this.itemCount = itemCount;
}
#Override
public String toString() {
return "ItemObject{\"id\": " +
this.id +
", \"itemCount\": " +
this.itemCount +
"}";
}
}
And the output of the program:
PlayerObject{"id": 1, "playerName": "SomePlayer1"}
ItemObject{"id": 3, "itemCount": 5}
null
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
public class Stackoverflow_68734414 {
private static Map<Integer, GameObject> OBJECT_MAP = new ConcurrentHashMap<>();
public static void main(String[] args) {
PlayerObject po = new PlayerObject();
ItemObject io = new ItemObject();
OBJECT_MAP.put(1, po);
OBJECT_MAP.put(2, io);
PlayerObject p1 = getObject(1, PlayerObject.class);
PlayerObject p2 = getObject(2, PlayerObject.class);
ItemObject i1 = getObject(1, ItemObject.class);
ItemObject i2 = getObject(2, ItemObject.class);
System.out.println(p1);
System.out.println(p2);
System.out.println(i1);
System.out.println(i2);
}
public static <T extends GameObject> T getObject(Integer id, Class<T> klass){
GameObject object = OBJECT_MAP.get(id);
if(Objects.nonNull(object) && (object.getClass() == klass)) {
return klass.cast(object);
} else{
return null;
}
}
}
class GameObject{
}
class PlayerObject extends GameObject {
}
class ItemObject extends GameObject{
}
Output is as expected:
PlayerObject#179d3b25
null
null
ItemObject#254989ff
Are you looking for something similar to this:
public boolean isItemObject(int id){
GameObject obj = OBJECT.get(id)
if(obj instanceof ItemObject && obj != null){
return true;
}
return false;
}
public boolean isPlayerObject(int id){
GameObject obj = OBJECT.get(id)
if(obj instanceof PlayerObject && obj != null){
return true;
}
return false;
}
public boolean isNPCObject(int id){
GameObject obj = OBJECT.get(id)
if(obj instanceof NpcObject && obj != null){
return true;
}
return false;
}
//...
final PlayerObject pObject = isPlayerObject(objectID) ? OBJECT.get(id) : null;

Pattern iterator

I have a task, which consists of pattern implementation (Iterator) and addition of the method iterator() in previously created classes Hotel and Tours. Unfortunately, I'm still new to Java, so I don't know how to use methods from IIterator for arraylist inter. Info - interface
public class IIterator<T> implements Iterator<T> {
private Object elements;
int index = 0;
public boolean hasNext() {
return index< Array.getLength(elements);
}
public T next() {
return (T) Array.get(elements, index++);
}
public void remove() {
throw new UnsupportedOperationException("remove");
}
}
public class Hotel implements Info, Serializable, Cloneable, Comparable{
public Iterator iterator() {
return new IIterator();
}
}
public class Tours implements Info, Serializable, Cloneable, Comparable{
public Iterator iterator() {
return new IIterator();
}
}
ArrayList<Info> inter = new ArrayList();
inter.add(new Hotel("Lara", 100, 5));
inter.add(new Hotel("Katya", 10, 1));
inter.add(new Tours("Lara", 1000, length));
inter.add(new Tours("HelsinkiPanorama", 1010, length));
EDITED
you can do this:
for (Info info : inter) {
System.out.println(info.getString());
}
or
Iterator<Info> it = inter.iterator();
while (it.hasNext()){
System.out.println(it.next().getString());
}
Previous answer
I'm not sure about your question, but if you want a simple example of iterator you can see this:
public class Hotel {
private String name;
public Hotel(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public class Tours implements Iterable<Hotel>{
private List<Hotel> hotels = new ArrayList<>();
public void addHotel(Hotel hotel){
hotels.add(hotel);
}
#Override
public Iterator<Hotel> iterator() {
return hotels.iterator();
}
}
Example:
public static void main(String[] args) {
Tours tours = new Tours();
tours.addHotel(new Hotel("hotel-0"));
tours.addHotel(new Hotel("hotel-1"));
tours.addHotel(new Hotel("hotel-2"));
tours.addHotel(new Hotel("hotel-3"));
for (Hotel hotel : tours) {
System.out.println(hotel.getName());
}
}
It prints:
hotel-0
hotel-1
hotel-2
hotel-3
If you want to see an example under the hood
public class Tours implements Iterable<Hotel>{
private int numHotels = 0;
private Hotel[] hotels = null;
public void addHotel(Hotel hotel){
if (hotels == null){
hotels = new Hotel[5];
} else if ( numHotels + 1 >= hotels.length){
hotels = Arrays.copyOf(hotels, numHotels + 5);
}
hotels[numHotels++] = hotel;
}
#Override
public Iterator<Hotel> iterator() {
return new HotelIterator();
}
private class HotelIterator implements Iterator<Hotel> {
private int index = 0;
#Override
public boolean hasNext() {
return index < numHotels;
}
#Override
public Hotel next() {
return hotels[index++];
}
}
}
Example 2:
public static void main(String[] args) {
Tours tours = new Tours();
tours.addHotel(new Hotel("hotel-0"));
tours.addHotel(new Hotel("hotel-1"));
tours.addHotel(new Hotel("hotel-2"));
tours.addHotel(new Hotel("hotel-3"));
for (Hotel hotel : tours) {
System.out.println(hotel.getName());
}
}
It prints:
hotel-0
hotel-1
hotel-2
hotel-3

JAVA : Bound mismatch: is not a valid substitute for the bounded parameter <E extends Comparable<E>>

i have the class BinaryTree:
public class BinaryTree<E extends Comparable<E>> extends AbstractTree<E> {
protected TreeNode<E> root;
protected int size = 0;
private final Comparator<? super E> comparator;
/** Create a default binary tree */
public BinaryTree() {
comparator = null;
}
/** Create a binary tree from an array of objects */
public BinaryTree(E[] objects) {
for (int i = 0; i < objects.length; i++)
insert(objects[i]);
}
public BinaryTree(E[] objects, Comparator<E> c) {
for (int i = 0; i < objects.length; i++)
insert(objects[i]);
}
//some getters, setters, insert, search and etc...
}
Also i have MyQueue Class:
public class MyQueue<E> {
private LinkedList<E> list = new LinkedList<E>();
public void enqueue(E e) {
list.addLast(e);
}
public E dequeue() {
return list.removeFirst();
}
public int getSize() {
return list.size();
}
public String toString() {
return "Queue: " + list.toString();
}
}
And finally i have the CreditCardTransaction class:
public class CreditCardTransaction {
private int cardNumber;
private String customerName;
private int amount;
public CreditCardTransaction(int cardNumber, String customerName, int amount) {
this.cardNumber = cardNumber;
this.customerName = customerName;
this.amount = amount;
}
public int getCardNumber() {
return cardNumber;
}
public void setCardNumber(int cardNumber) {
this.cardNumber = cardNumber;
}
public String getCustomerName() {
return customerName;
}
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
}
In the main i wrote:
BinaryTree<MyQueue<CreditCardTransaction>> e = new BinaryTree<MyQueue<CreditCardTransaction>>();
i get the error:
Bound mismatch: The type MyQueue<CreditCardTransaction> is not a valid substitute for the bounded parameter <E extends Comparable<E>> of the type BinaryTree<E>
I try all kind of mix with the types and any time the eclipse gave me this error, any help please?
EDIT
I added to MyQueue
public class MyQueue<E> implements Comparable<E>{
#Override
public int compareTo(E o) {
// TODO Auto-generated method stub
return 0;
}
}
and in the main it still gave me the error:
Bound mismatch: The type MyQueue<CreditCardTransaction> is not a valid
substitute for the bounded parameter <E extends Comparable<E>> of the
type BinaryTree<E>
MyQueue does not implement Comparable, so it can't substitute the type parameter of BinaryTree.
You can either remove the extends Comparable<E> bound from BinaryTree if you don't need it, or change MyQueue to implement Comparable<MyQueue<E>>.

Android java loop through object list

My code connects to an Api, takes all Json values and stores them all in a object list resultClass. How I loop through the list and display all name properties of the objects?
This is the code I am using. The JSON values are sent with the method call as parameter with name object. Then loops and takes all objects and stores them in a list.
public void onResponse(JSONObject object) {
Log.i("gw2Log", "Json Response" + object);
resultClass resultClass = new resultClass();
try {
resultClass.setCount(object.getInt("count"));
resultClass.setPage(object.getInt("page"));
resultClass.setLast_page(object.getInt("last_page"));
resultClass.setTotal(object.getInt("total"));
JSONArray list = new JSONArray(object.getString("results"));
for (int i = 0; i < resultClass.getTotal(); i++) {
JSONObject resultsObject = list.getJSONObject(i);
resultClass.setData_id(resultsObject
.getInt("data_id"));
resultClass.setName(resultsObject
.getString("name"));
resultClass.setRarity(resultsObject
.getInt("rarity"));
resultClass.setRestriction_level(resultsObject
.getInt("restriction_level"));
resultClass.setImg(resultsObject
.getString("img"));
resultClass.setType_id(resultsObject
.getInt("type_id"));
resultClass.setSub_type_id(resultsObject
.getInt("sub_type_id"));
resultClass.setPrice_last_changed(resultsObject
.getString("price_last_changed"));
resultClass.setMax_offer_unit_price(resultsObject
.getInt("max_offer_unit_price"));
resultClass.setMin_sale_unit_price(resultsObject
.getInt("min_sale_unit_price"));
resultClass.setOffer_availability(resultsObject
.getInt("offer_availability"));
resultClass.setSale_availability(resultsObject
.getInt("sale_availability"));
resultClass.setSale_price_change_last_hour(resultsObject
.getInt("sale_price_change_last_hour"));
resultClass.setOffer_price_change_last_hour(resultsObject
.getInt("offer_price_change_last_hour"));
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for(int i = 0; i < resultClass.total; i++) {
Log.i("gw2Log", resultClass.name[i]);
}
}
This is the Json response i am logging
Json Response{"total":6,"last_page":1,"results":[{"sale_availability":0,"offer_availability":0,"img":"https:\/\/render.guildwars2.com\/file\/01D07FABAE26C0E5240892B00DA7AF90AB0EA022\/455828.png","rarity":7,"type_id":16,"sale_price_change_last_hour":0,"max_offer_unit_price":0,"data_id":19648,"price_last_changed":"2015-04-20 20:23:48 UTC","offer_price_change_last_hour":0,"name":"Gift of Twilight","min_sale_unit_price":0,"restriction_level":0,"sub_type_id":0},{"sale_availability":0,"offer_availability":0,"img":"https:\/\/render.guildwars2.com\/file\/CE3AF0B7B9BB6244726779F5B6A930541BA6C15F\/456031.png","rarity":5,"type_id":18,"sale_price_change_last_hour":0,"max_offer_unit_price":0,"data_id":49191,"price_last_changed":"2015-04-20 20:23:48 UTC","offer_price_change_last_hour":0,"name":"Twilight","min_sale_unit_price":0,"restriction_level":80,"sub_type_id":6},{"sale_availability":23,"offer_availability":20643,"img":"https:\/\/render.guildwars2.com\/file\/CE3AF0B7B9BB6244726779F5B6A930541BA6C15F\/456031.png","rarity":7,"type_id":18,"sale_price_change_last_hour":0,"max_offer_unit_price":27500000,"data_id":30704,"price_last_changed":"2015-04-20 20:17:57 UTC","offer_price_change_last_hour":0,"name":"Twilight","min_sale_unit_price":31959998,"restriction_level":80,"sub_type_id":6},{"sale_availability":0,"offer_availability":0,"img":"https:\/\/render.guildwars2.com\/file\/D04EF6FDE3DBC26E7BB109EB4F52057FEAD8619E\/699325.png","rarity":1,"type_id":4,"sale_price_change_last_hour":0,"max_offer_unit_price":0,"data_id":65578,"price_last_changed":"2015-04-20 20:23:48 UTC","offer_price_change_last_hour":0,"name":"Twilight Arbor Armor Box","min_sale_unit_price":0,"restriction_level":0,"sub_type_id":0},{"sale_availability":0,"offer_availability":0,"img":"https:\/\/render.guildwars2.com\/file\/666209104CCB024D53359C0EA0A299076E610771\/65704.png","rarity":1,"type_id":4,"sale_price_change_last_hour":0,"max_offer_unit_price":0,"data_id":65577,"price_last_changed":"2015-04-20 20:23:48 UTC","offer_price_change_last_hour":0,"name":"Twilight Arbor Token Loot Box","min_sale_unit_price":0,"restriction_level":0,"sub_type_id":0},{"sale_availability":0,"offer_availability":0,"img":"https:\/\/render.guildwars2.com\/file\/2626184EDDC254B4F7634A04F878062C6B2AF20D\/780372.png","rarity":1,"type_id":4,"sale_price_change_last_hour":0,"max_offer_unit_price":0,"data_id":65579,"price_last_changed":"2015-04-20 20:23:48 UTC","offer_price_change_last_hour":0,"name":"Twilight Arbor Weapons Box","min_sale_unit_price":0,"restriction_level":0,"sub_type_id":0}],"count":6,"page":1}
When digging around for a solution and checking the actual error it says it expects and array but a string is given Log.i("gw2Log", resultClass.name[i]);
When I loop through this Log call Log.i("gw2Log", resultClass.name); it displays the last objects name property the amount it loops.
EDIT:
On request to include my resultClass.java:
public class resultClass {
public int data_id;
public String name;
public int rarity;
public int restriction_level;
public String img;
public int type_id;
public int sub_type_id;
public String price_last_changed;
public int max_offer_unit_price;
public int min_sale_unit_price;
public int offer_availability;
public int sale_availability;
public int sale_price_change_last_hour;
public int offer_price_change_last_hour;
public int count;
public int page;
public int last_page;
public int total;
public int getData_id() {
return data_id;
}
public void setData_id(int data_id) {
this.data_id = data_id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getRarity() {
return rarity;
}
public void setRarity(int rarity) {
this.rarity = rarity;
}
public int getRestriction_level() {
return restriction_level;
}
public void setRestriction_level(int restriction_level) {
this.restriction_level = restriction_level;
}
public String getImg() {
return img;
}
public void setImg(String img) {
this.img = img;
}
public int getType_id() {
return type_id;
}
public void setType_id(int type_id) {
this.type_id = type_id;
}
public int getSub_type_id() {
return sub_type_id;
}
public void setSub_type_id(int sub_type_id) {
this.sub_type_id = sub_type_id;
}
public String getPrice_last_changed() {
return price_last_changed;
}
public void setPrice_last_changed(String price_last_changed) {
this.price_last_changed = price_last_changed;
}
public int getMax_offer_unit_price() {
return max_offer_unit_price;
}
public void setMax_offer_unit_price(int max_offer_unit_price) {
this.max_offer_unit_price = max_offer_unit_price;
}
public int getMin_sale_unit_price() {
return min_sale_unit_price;
}
public void setMin_sale_unit_price(int min_sale_unit_price) {
this.min_sale_unit_price = min_sale_unit_price;
}
public int getOffer_availability() {
return offer_availability;
}
public void setOffer_availability(int offer_availability) {
this.offer_availability = offer_availability;
}
public int getSale_availability() {
return sale_availability;
}
public void setSale_availability(int sale_availability) {
this.sale_availability = sale_availability;
}
public int getSale_price_change_last_hour() {
return sale_price_change_last_hour;
}
public void setSale_price_change_last_hour(int sale_price_change_last_hour) {
this.sale_price_change_last_hour = sale_price_change_last_hour;
}
public int getOffer_price_change_last_hour() {
return offer_price_change_last_hour;
}
public void setOffer_price_change_last_hour(int offer_price_change_last_hour) {
this.offer_price_change_last_hour = offer_price_change_last_hour;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public int getLast_page() {
return last_page;
}
public void setLast_page(int last_page) {
this.last_page = last_page;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
}
try something like this
first make a new object something like MyObject
public class MyObject {
public int data_id;
public String name;
public int rarity;
public int restriction_level;
public String img;
public int type_id;
public int sub_type_id;
public String price_last_changed;
public int max_offer_unit_price;
public int min_sale_unit_price;
public int offer_availability;
public int sale_availability;
public int sale_price_change_last_hour;
public int offer_price_change_last_hour;
public int getData_id() {
return data_id;
}
public void setData_id(int data_id) {
this.data_id = data_id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getRarity() {
return rarity;
}
public void setRarity(int rarity) {
this.rarity = rarity;
}
public int getRestriction_level() {
return restriction_level;
}
public void setRestriction_level(int restriction_level) {
this.restriction_level = restriction_level;
}
public String getImg() {
return img;
}
public void setImg(String img) {
this.img = img;
}
public int getType_id() {
return type_id;
}
public void setType_id(int type_id) {
this.type_id = type_id;
}
public int getSub_type_id() {
return sub_type_id;
}
public void setSub_type_id(int sub_type_id) {
this.sub_type_id = sub_type_id;
}
public String getPrice_last_changed() {
return price_last_changed;
}
public void setPrice_last_changed(String price_last_changed) {
this.price_last_changed = price_last_changed;
}
public int getMax_offer_unit_price() {
return max_offer_unit_price;
}
public void setMax_offer_unit_price(int max_offer_unit_price) {
this.max_offer_unit_price = max_offer_unit_price;
}
public int getMin_sale_unit_price() {
return min_sale_unit_price;
}
public void setMin_sale_unit_price(int min_sale_unit_price) {
this.min_sale_unit_price = min_sale_unit_price;
}
public int getOffer_availability() {
return offer_availability;
}
public void setOffer_availability(int offer_availability) {
this.offer_availability = offer_availability;
}
public int getSale_availability() {
return sale_availability;
}
public void setSale_availability(int sale_availability) {
this.sale_availability = sale_availability;
}
public int getSale_price_change_last_hour() {
return sale_price_change_last_hour;
}
public void setSale_price_change_last_hour(int sale_price_change_last_hour) {
this.sale_price_change_last_hour = sale_price_change_last_hour;
}
public int getOffer_price_change_last_hour() {
return offer_price_change_last_hour;
}
public void setOffer_price_change_last_hour(int offer_price_change_last_hour) {
this.offer_price_change_last_hour = offer_price_change_last_hour;
}
}
then make your resultClass look like this
public class resultClass {
public int count;
public int page;
public int last_page;
public int total;
public ArrayList<MyObject> myObjects = new ArrayList();
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public int getLast_page() {
return last_page;
}
public void setLast_page(int last_page) {
this.last_page = last_page;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public MyObject getObject(int pos){
return myObjects.get(pos);
}
public void addObject(MyObject object)
{
myObjects.add(object);
}
}
then your response should be something like this
public void onResponse(JSONObject object) {
Log.i("gw2Log", "Json Response" + object);
resultClass resultClass = new resultClass();
try {
resultClass.setCount(object.getInt("count"));
resultClass.setPage(object.getInt("page"));
resultClass.setLast_page(object.getInt("last_page"));
resultClass.setTotal(object.getInt("total"));
JSONArray list = new JSONArray(object.getString("results"));
for (int i = 0; i < resultClass.getTotal(); i++) {
JSONObject resultsObject = list.getJSONObject(i);
MyObject temp = new MyObject();
temp.setData_id(resultsObject
.getInt("data_id"));
temp.setName(resultsObject
.getString("name"));
temp.setRarity(resultsObject
.getInt("rarity"));
temp.setRestriction_level(resultsObject
.getInt("restriction_level"));
temp.setImg(resultsObject
.getString("img"));
temp.setType_id(resultsObject
.getInt("type_id"));
temp.setSub_type_id(resultsObject
.getInt("sub_type_id"));
temp.setPrice_last_changed(resultsObject
.getString("price_last_changed"));
temp.setMax_offer_unit_price(resultsObject
.getInt("max_offer_unit_price"));
temp.setMin_sale_unit_price(resultsObject
.getInt("min_sale_unit_price"));
temp.setOffer_availability(resultsObject
.getInt("offer_availability"));
temp.setSale_availability(resultsObject
.getInt("sale_availability"));
temp.setSale_price_change_last_hour(resultsObject
.getInt("sale_price_change_last_hour"));
temp.setOffer_price_change_last_hour(resultsObject
.getInt("offer_price_change_last_hour"));
resultClass.addObject(temp);
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for(int i = 0; i < resultClass.total; i++) {
Log.i("gw2Log", resultClass.getObject(i).name);
}
}
You could try this code. You wanted to use table of objects, but you created just single object. Create arrayList of your resultClass and then use simplier 'for' for your list
public void onResponse(JSONObject object) {
Log.i("gw2Log", "Json Response" + object);
List<resultClass> resultClassList = new ArrayList<resultClass>();
resultClass resultClass = new resultClass();
try {
resultClass.setCount(object.getInt("count"));
resultClass.setPage(object.getInt("page"));
resultClass.setLast_page(object.getInt("last_page"));
resultClass.setTotal(object.getInt("total"));
JSONArray list = new JSONArray(object.getString("results"));
for (int i = 0; i < resultClass.getTotal(); i++) {
JSONObject resultsObject = list.getJSONObject(i);
resultClass.setData_id(resultsObject
.getInt("data_id"));
resultClass.setName(resultsObject
.getString("name"));
resultClass.setRarity(resultsObject
.getInt("rarity"));
resultClass.setRestriction_level(resultsObject
.getInt("restriction_level"));
resultClass.setImg(resultsObject
.getString("img"));
resultClass.setType_id(resultsObject
.getInt("type_id"));
resultClass.setSub_type_id(resultsObject
.getInt("sub_type_id"));
resultClass.setPrice_last_changed(resultsObject
.getString("price_last_changed"));
resultClass.setMax_offer_unit_price(resultsObject
.getInt("max_offer_unit_price"));
resultClass.setMin_sale_unit_price(resultsObject
.getInt("min_sale_unit_price"));
resultClass.setOffer_availability(resultsObject
.getInt("offer_availability"));
resultClass.setSale_availability(resultsObject
.getInt("sale_availability"));
resultClass.setSale_price_change_last_hour(resultsObject
.getInt("sale_price_change_last_hour"));
resultClass.setOffer_price_change_last_hour(resultsObject
.getInt("offer_price_change_last_hour"));
resultClassList.add(resultClass);
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for(resultClass result : resultClassList) {
Log.i("gw2Log", result.name);
}
}
Ok, I'm pretty sure of several things:
Tomer Shemesh is right, you are overriding your resultClass object on every iteration.
You wanna make arrays out of your normal variables in the resultClass so you can actually store more than one Item.
About that error you're getting:
It occurs in the lower for loop, where you want to log the names, right?
resultClass.nameis a String variable, it holds exactly one string of characters. You are trying to get a string out of an array by saying something like resultClass.name[i]. For that to work youu need to decrlare it as a string array, holding several string like public String[] name;, and in the constructor initialize it with a given capactiy like name = new String[cap];. Or you use an ArrayList<String> instead, which grows dynmically, but uses own getters and setters instead of the easy name[index] functions of an array.
Sorry, but I don't really want to write the right code here, as pretty much the whole thing needs to be rewritten, I hope this will help you rewrite it yourself though.

How do I make my ImmutableList sortable in its ObservableList wrapper?

I have my own implementation of ObservableList called ObservableImmutableList. It wraps a Guava ImmutableList with the ObservableList interface so I can fully utilize ImmutableList easily with JavaFX. There is nothing mutable about it except it allows another ImmutableList to be swapped in as the backing list using the set() method (and notify all listeners/bindings of the change).
However, one problem I ran into is the ObservableImmutableList cannot be sorted. I cannot extend or implement SortedList, so how do I implement it into this class?
I tried to create a method asSorted() which returns the ObservableImmutableList wrapped in a SortedList. But it also would not work. Is there some kind of simple abstract layer I can use to keep the list Immutable but allow the values to be resorted in the abstracted layer?
public final class ObservableImmutableList<T> implements ObservableList<T> {
private volatile ImmutableList<T> backingList;
private final LazyProperty<SortedList<T>> sortedList = LazyProperty.forSupplier(() -> new SortedList<>(this));
private final CopyOnWriteArrayList<ListChangeListener<? super T>> listeners = new CopyOnWriteArrayList<>();
private final CopyOnWriteArrayList<InvalidationListener> invalidationListeners = new CopyOnWriteArrayList<>();
private final ObjectProperty<ObservableList<T>> property;
private ObservableImmutableList(ImmutableList<T> immutableList) {
this.backingList = immutableList;
this.property = new SimpleObjectProperty<ObservableList<T>>(this);
}
public static <T> ObservableImmutableList<T> of(ImmutableList<T> immutableList) {
return new ObservableImmutableList<T>(immutableList);
}
public SortedList<T> asSorted() {
return sortedList.get();
}
public void set(ImmutableList<T> immutableList) {
this.property.setValue(this);
final ImmutableList<T> oldList = this.backingList;
final ImmutableList<T> newList = immutableList;
listeners.forEach(l -> l.onChanged(new Change<T>(this) {
private int changeNum = 0;
#Override
public boolean next() {
changeNum++;
return changeNum <= 2 ? true : false;
}
#Override
public boolean wasUpdated() {
return true;
}
#Override
public void reset() {
// TODO Auto-generated method stub
}
#Override
public int getFrom() {
return 0;
}
#Override
public int getTo() {
return changeNum == 1 ? oldList.size() - 1 : newList.size() - 1;
}
#Override
public List<T> getRemoved() {
return changeNum == 1 ? oldList : ImmutableList.of();
}
#Override
public List<T> getAddedSubList() {
return changeNum == 1 ? ImmutableList.of() : newList;
}
#Override
protected int[] getPermutation() {
int[] permutations = new int[changeNum == 1 ? oldList.size() : newList.size()];
for (int i = 0; i < permutations.length; i++) {
permutations[i] = i;
}
return permutations;
}
}));
this.backingList = immutableList;
invalidationListeners.forEach(l -> l.invalidated(this));
}
public ImmutableList<T> get() {
return backingList;
}
public ObjectProperty<ObservableList<T>> asProperty() {
return property;
}
#Override
public int size() {
return backingList.size();
}
#Override
public boolean isEmpty() {
return backingList.isEmpty();
}
#Override
public boolean contains(Object o) {
return backingList.contains(o);
}
#Override
public Iterator<T> iterator() {
return backingList.iterator();
}
#Override
public Object[] toArray() {
return backingList.toArray();
}
#Override
public <B> B[] toArray(B[] a) {
return backingList.toArray(a);
}
#Override #Deprecated
public boolean add(T e) {
return backingList.add(e);
}
#Override #Deprecated
public boolean remove(Object o) {
return backingList.remove(o);
}
#Override
public boolean containsAll(Collection<?> c) {
return backingList.containsAll(c);
}
#Override #Deprecated
public boolean addAll(Collection<? extends T> c) {
return backingList.addAll(c);
}
#Override #Deprecated
public boolean addAll(int index, Collection<? extends T> c) {
return backingList.addAll(index, c);
}
#Override #Deprecated
public boolean removeAll(Collection<?> c) {
return backingList.removeAll(c);
}
#Override #Deprecated
public boolean retainAll(Collection<?> c) {
return backingList.retainAll(c);
}
#Override #Deprecated
public void clear() {
backingList.clear();
}
#Override
public T get(int index) {
return backingList.get(index);
}
#Override #Deprecated
public T set(int index, T element) {
return backingList.set(index, element);
}
#Override #Deprecated
public void add(int index, T element) {
backingList.add(index, element);
}
#Override #Deprecated
public T remove(int index) {
return backingList.remove(index);
}
#Override
public int indexOf(Object o) {
return backingList.indexOf(o);
}
#Override
public int lastIndexOf(Object o) {
return backingList.lastIndexOf(o);
}
#Override
public ListIterator<T> listIterator() {
return backingList.listIterator();
}
#Override
public ListIterator<T> listIterator(int index) {
return backingList.listIterator(index);
}
#Override
public ImmutableList<T> subList(int fromIndex, int toIndex) {
return backingList.subList(fromIndex, toIndex);
}
#Override
public void addListener(InvalidationListener listener) {
invalidationListeners.add(listener);
}
#Override
public void removeListener(InvalidationListener listener) {
invalidationListeners.remove(listener);
}
#Override
public void addListener(ListChangeListener<? super T> listener) {
listeners.add(listener);
}
#Override
public void removeListener(ListChangeListener<? super T> listener) {
listeners.remove(listener);
}
#Override #Deprecated
public boolean addAll(T... elements) {
return backingList.addAll(ImmutableList.copyOf(elements));
}
#Override #Deprecated
public boolean setAll(T... elements) {
return false;
}
#Override #Deprecated
public boolean setAll(Collection<? extends T> col) {
return false;
}
#Override #Deprecated
public boolean removeAll(T... elements) {
return backingList.removeAll(ImmutableList.copyOf(elements));
}
#Override #Deprecated
public boolean retainAll(T... elements) {
return false;
}
#Override #Deprecated
public void remove(int from, int to) {
}
#Override
public String toString() {
return backingList.toString();
}
}
The part you asked about: a SortedList is just a wrapper around its backing list, it does not change it in any way. So you can wrap any list - mutable or not - into a SortedList and use that in the TableView. In the example of your previous question:
ObservableList<NumericCombo> immutable =
FXCollections.unmodifiableObservableList(values);
// new ImmutableObservableList<>(values);
TableView<NumericCombo> tableView = new TableView<>();
SortedList sorted = new SortedList(immutable);
tableView.setItems(sorted);
sorted.comparatorProperty().bind(tableView.comparatorProperty());
The part you did not ask about (how to get the notifications right).
don't implement ObservableList from scratch, instead go from ObservableListBase
when swapping out the backing list, call the support methods provided by super to notify the listeners
A simple example:
public class ImmutableObservableList<E> extends ObservableListBase<E> {
private List<E> backing;
public ImmutableObservableList(List<E> backingList) {
this.backing = backingList;
}
public void setBackingList(List<E> backingList) {
beginChange();
if (this.backing != null) {
nextRemove(0, this.backing);
}
this.backing = backingList;
if (backingList != null) {
nextAdd(0, backingList.size());
}
endChange();
}
#Override
public E get(int index) {
if (backing == null) throw new IndexOutOfBoundsException();
return backing.get(index);
}
#Override
public int size() {
return backing != null ? backing.size() : 0;
}
}

Categories

Resources