Read and write Parcel when using ArrayList of ArrayList - java

I'm trying to read and write this ArrayList structured as well: ArrayList<ArrayList<Pair<Float,Float>>> points I've seen that the only way would by using the class inside the external ArrayList, but in this case I haven't it. This is my full class, how do I can implement it?
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Pair;
import java.io.Serializable;
import java.util.ArrayList;
public class Cornice implements Serializable, Parcelable {
private String number;
private ArrayList<ArrayList<Pair<Float,Float>>> points;
public Cornice(String n, ArrayList<ArrayList<Pair<Float,Float>>> p) {
number = n;
if (p!=null) points = new ArrayList<>(p);
else points=new ArrayList<>();
}
protected Cornice(Parcel in) {
number = in.readString();
points = //MISSING
}
public String getNumber () {
return number;
}
public ArrayList<ArrayList<Pair<Float,Float>>> getPoints () {
return points;
}
public static final Creator<Cornice> CREATOR = new Creator<Cornice>() {
#Override
public Cornice createFromParcel(Parcel in) {
return new Cornice(in);
}
#Override
public Cornice[] newArray(int size) {
return new Cornice[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(number);
//MISSING
}
}

Pair is neither Parcelable, nor Serializable, so what you are trying to do won't work. You will have to change the data structure you use to hold the points to something else. For example you can convert it something like this:
private ArrayList<ArrayList<Float[]>> points;
or even (if you do not want to support null values) to:
private ArrayList<ArrayList<float[]>> points;

Related

Java Serialize with Inheritance?

Here is the Goals.java
public abstract class Goals {
private String score;
public Goals(String str) {
this.score = str;
}
String getGoals() {
return this.score;
}
void doSomething(score) {
}
}
Here is the Game.java
public class Game implements Serializable {
public String name;
public int game_num;
public int opp;
public int player;
public Goals goal;
public Game(int i, int i2, int i3) {
this.player = i;
this.game_num = i2;
this.opp = i3;
}
public Game(String str, Goals goal) {
this.name = str;
this.goal = goal;
}
}
Can we create a Serialized Object in a way that after it is deserialized and casted to Game , it will set score inside Goals.java ?
Also, can you manipulate / overwrite doSomething method if the serialized data comes from untrusted source?
In the way you are trying to manipulates your objects, I think you can do that Goals implements Serializable, and Game implements Goals:
public abstract class Goals implements Serializable{
private String score;
public Goals(String str) {
this.score = str;
}
String getGoals() {
return this.score;
}
void doSomething(score) {
}
}
for Game
public class Game extends Goals {
public String name;
public int game_num;
public int opp;
public int player;
public Game(int i, int i2, int i3) {
this.player = i;
this.game_num = i2;
this.opp = i3;
}
public Game(String str) {
//create constructor also including the properties of Goals
Super()...
}
}
As mentioned in comments, implement Goals and its implementation with Serializable and also implement default constructor in both the classes .
Working piece of code:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
abstract class Goals implements Serializable{
private String score;
public Goals() {
this(null);
}
public Goals(String str) {
this.score = str;
}
String getGoals() {
return this.score;
}
void doSomething(int score) {
}
}
class Game implements Serializable {
public String name;
public int game_num;
public int opp;
public int player;
public Goals goal;
public Game(int i, int i2, int i3) {
this.player = i;
this.game_num = i2;
this.opp = i3;
}
public Game(String str, Goals goal) {
this.name = str;
this.goal = goal;
}
}
class GoalImpl extends Goals implements Serializable{
public GoalImpl() {
}
public GoalImpl(String str) {
super(str);
}
}
public class Main{
public static void main(String...s) {
Goals goal = new GoalImpl("20");
Game game = new Game("name",goal);
try
{
//Saving of object in a file
FileOutputStream file = new FileOutputStream("gamefile.ser");
ObjectOutputStream out = new ObjectOutputStream(file);
// Method for serialization of object
out.writeObject(game);
out.close();
file.close();
System.out.println("Object has been serialized");
}
catch(IOException ex)
{
ex.printStackTrace();
System.out.println("IOException is caught");
}
Game object1 = null;
// Deserialization
try
{
// Reading the object from a file
FileInputStream file = new FileInputStream("gamefile.ser");
ObjectInputStream in = new ObjectInputStream(file);
// Method for deserialization of object
object1 = (Game)in.readObject();
in.close();
file.close();
System.out.println("Object has been deserialized ");
System.out.println("score = " + object1.goal.getGoals());
}
catch(IOException ex)
{
ex.printStackTrace();
System.out.println("IOException is caught");
}
catch(ClassNotFoundException ex)
{
System.out.println("ClassNotFoundException is caught");
}
}
}
Output:
Object has been serialized
Object has been deserialized
score = 20
PS:
An advice to make score as integer as otherwise you will not be able to do basic operations like increase score or decrease score using inbuilt operators (+ , - )
Always place proper getter setter name like getScore() and setScore int this case.
Do try to make constructors in sync, for example in case of Game constructor with player id, game num and opposition is called, Game name and Goals will never be initialized, better to initialize them with default value or other good option is make another constructor accepting all parameters and then from individual constructos you can call master constructor and pass default values for those which are not passed by the calling method.

Jenetics custom gene/chromosome

I have started experimenting with the Jenetics library, however I am having some issues with trying to make a very easy "custom" set of gene/chromosomes.
What I tried to do was to create a custom chromosome with a different (random) number of custom genes inside. The genes simply contain an integer value, just for the sake of simplicity. For the same simplicity, the contents of a gene can only be numbers ranging from 0 to 9 and a Gene is considered valid only if it does NOT contain the number 9 (again, retardedly simple, but I just wanted to make them custom)
Here is my code:
CustomGene:
public class CustomGene implements Gene<Integer, CustomGene> {
private Integer value;
private CustomGene(Integer value) {
this.value = value;
}
public static CustomGene of(Integer value) {
return new CustomGene(value);
}
public static ISeq<CustomGene> seq(Integer min, Integer max, int length) {
Random r = RandomRegistry.getRandom();
return MSeq.<CustomGene>ofLength(length).fill(() ->
new CustomGene(random.nextInt(r, min, max))
).toISeq();
}
#Override
public Integer getAllele() {
return value;
}
#Override
public CustomGene newInstance() {
final Random random = RandomRegistry.getRandom();
return new CustomGene(Math.abs(random.nextInt(9)));
}
#Override
public CustomGene newInstance(Integer integer) {
return new CustomGene(integer);
}
#Override
public boolean isValid() {
return value != 9;
}
}
CustomChromosome:
import org.jenetics.Chromosome;
import org.jenetics.util.ISeq;
import org.jenetics.util.RandomRegistry;
import java.util.Iterator;
import java.util.Random;
public class CustomChromosome implements Chromosome<CustomGene> {
private ISeq<CustomGene> iSeq;
private final int length;
public CustomChromosome(ISeq<CustomGene> genes) {
this.iSeq = genes;
this.length = iSeq.length();
}
public static CustomChromosome of(ISeq<CustomGene> genes) {
return new CustomChromosome(genes);
}
#Override
public Chromosome<CustomGene> newInstance(ISeq<CustomGene> iSeq) {
this.iSeq = iSeq;
return this;
}
#Override
public CustomGene getGene(int i) {
return iSeq.get(i);
}
#Override
public int length() {
return iSeq.length();
}
#Override
public ISeq<CustomGene> toSeq() {
return iSeq;
}
#Override
public Chromosome<CustomGene> newInstance() {
final Random random = RandomRegistry.getRandom();
ISeq<CustomGene> genes = ISeq.empty();
for (int i = 0; i < length; i++) {
genes = genes.append(CustomGene.of(Math.abs(random.nextInt(9))));
}
return new CustomChromosome(genes);
}
#Override
public Iterator<CustomGene> iterator() {
return iSeq.iterator();
}
#Override
public boolean isValid() {
return iSeq.stream().allMatch(CustomGene::isValid);
}
}
Main:
import org.jenetics.Genotype;
import org.jenetics.Optimize;
import org.jenetics.engine.Engine;
import org.jenetics.engine.EvolutionResult;
import org.jenetics.util.Factory;
import org.jenetics.util.RandomRegistry;
import java.util.Random;
public class Main {
private static int maxSum = - 100;
private static Integer eval(Genotype<CustomGene> gt) {
final int sum = gt.getChromosome().stream().mapToInt(CustomGene::getAllele).sum();
if(sum > maxSum)
maxSum = sum;
return sum;
}
public static void main(String[] args) {
final Random random = RandomRegistry.getRandom();
Factory<Genotype<CustomGene>> g =
Genotype.of(CustomChromosome.of(CustomGene.seq(0, 9, Math.abs(random.nextInt(9)) + 1)));
Engine<CustomGene, Integer> engine = Engine
.builder(Main::eval, g)
.optimize(Optimize.MAXIMUM)
.populationSize(100)
.build();
Genotype<CustomGene> result = engine.stream().limit(10000)
.collect(EvolutionResult.toBestGenotype());
System.out.println(eval(result));
result.getChromosome().stream().forEach(i -> {
System.out.print(i.getAllele() + " ");
});
System.out.println();
System.out.println(maxSum);
}
}
I do not understand why I get this output:
13 (evaluated result)
1 8 0 4 (all the alleles form the genes of the chosen chromosome)
32 (the actual maximum fitness found)
We can clearly see a difference between the genotype which had the biggest fitness function and the chosen genotype. Why?
I know I'm doing something wrong and it's probably a silly mistake, but I really can't seem to understand what I am doing wrong. Could you please help me out?
Lots of thanks!
As posted by the creator of the library here, the answer was:
you violated the contract of the Chromosome.newInstance(ISeq) method. This method must return a new chromosome instance. After fixing this
#Override
public Chromosome<CustomGene> newInstance(ISeq<CustomGene> iSeq) {
return new CustomChromosome(iSeq);
}

Java Collections Binary Search : The method binarySearch in the type Collections is not applicable for the arguments

I am trying to design a ride sharing system. Here is my base object
package rider;
import java.util.TreeMap;
public class Uber{
String driver;
TreeMap<Float,String> destination;
public Uber(String d)
{
driver=d;
destination = new TreeMap<Float,String>();
}
private void addTimeDest(float tm, String dest)
{
destination.put(tm, dest);
}
float getTsum() {
float tsum=0;
for (float f : this.destination.keySet())
tsum+=f;
return tsum;
}
}
So, each object has a driver and an associated time<->destination map for that driver. Ultimately, i want to sort a list of such objects by the time field i.e. the key of the treemap.
and here is the iterator class i created for the above
package rider;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
public class UberIterator implements Iterator<Uber> {
int currIndex=0;
ArrayList<Uber> uList;
Comparator<Uber> timeComparator = new Comparator<Uber>(){
public int compare(Uber u1, Uber u2) {
return (int) (u1.getTsum()-u2.getTsum());
}
};
public UberIterator(ArrayList<Uber> nList)
{
uList=nList;
Collections.sort(uList,timeComparator);
}
public boolean hasNext() {
return currIndex<uList.size();
}
public Uber next() {
return uList.get(currIndex++);
}
#Override
public void remove() {
uList.remove(currIndex--);
}
public void remove(String d) {
int rindex=-1;
for(int u=0 ; u<currIndex; u++)
{
if(uList.get(u).driver.equals(d))
{
rindex=u;
break;
}
}
if(rindex<0)
System.out.println("Driver not found.");
else
{
uList.remove(rindex);
currIndex--;
}
}
public void remove(float tm) {
int rindex=Collections.binarySearch(uList, tm, timeComparator);
if(rindex<0)
{
System.out.println("Exact time not found. Closest will be removed.");
}
else
{
uList.remove(rindex);
currIndex--;
}
}
}
basically, with the comparator
Comparator<Uber> timeComparator = new Comparator<Uber>(){
public int compare(Uber u1, Uber u2) {
return (int) (u1.getTsum()-u2.getTsum());
}
};
i am trying to sort by the key of the internal treemap. but i get this error
The method binarySearch(List<? extends T>, T, Comparator<? super T>) in the type Collections is not applicable for the arguments (ArrayList<Uber>, float, Comparator<Uber>)
at
int rindex=Collections.binarySearch(uList, tm, timeComparator);
how should i correct my implementation?
Follow Up
is there a way to override Collections.binarySearch ? what if Uber implements Comparable and there i define the compare method as above? Shouldn't that automatically search with the time dimension? Otherwise what is the benefit of defining custom comparators for sorting? The sole reason i want to sort the list in a certain way is to be able to search it efficiently later on.
package rider;
import java.util.TreeMap;
public class Uber implements Comparable<Uber> {
String driver;
TreeMap<Float,String> destination;
public Uber(String d)
{
driver=d;
destination = new TreeMap<Float,String>();
}
private void addTimeDest(float tm, String dest)
{
destination.put(tm, dest);
}
public int compareTo(Uber u) {
return (int) (this.getTsum()-u.getTsum());
}
float getTsum() {
float tsum=0;
for (float f : this.destination.keySet())
tsum+=f;
return tsum;
}
}
int rindex=Collections.binarySearch(uList, tm, timeComparator);
You cannot search for a float in a List<Uber>.
Your alternatives...frankly aren't that great. You could create a fake Uber containing your tm value and pass that to Collections.binarySearch. You could use a library like Guava, call Lists.transform(ubers, getTmFunction) to create a view, and pass that to Collections.binarySearch. You could reimplement binary search yourself.

Trying to sand class object between intents by parcelable

I have a bit trouble implementing Parcelable. Here's how I did it:
public class Player implements Parcelable{
String name;
int score;
#Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(score);
}
public Player(Parcel source){
score = source.readInt();
name = source.readString();
}
}
public class MyCreator implements Parcelable.Creator<Player> {
#Override
public Player createFromParcel(Parcel source) {
return new Player(source);
}
#Override
public Player[] newArray(int size) {
return new Player[size];
}
}
This was the whole code implementing Parcelable. Now I'm trying to create a new class object:
Player newPlayer = new Player(null);
newPlayer.name = text;
newPlayer.score = 0;
playersParceledData.add(newPlayer);
zacniIgro.putParcelableArrayListExtra("parceledData", playersParceledData);
This is the line that is bothering me:
Player newPlayer = new Player(null);
Is the fact that I just insrted "null" okay? Or do I have to insert something else between those ()? I was following this example and this isn't explained in it. It says that a new object should be created like this:
Player newPlayer = new Player();
But I am not allowed to do this since I made a constructor.
Create an additional constructor for use cases you're not using Parcel to construct your object, for example
public class Player implements Parcelable{
/* ... */
public Player(Parcel source){
/* ... */
}
public Player(int score, String name){
this.score = score;
this.name = name;
}
}
Then you can construct objects both from Parcel and using an int and an String:
final Player aPlayer = new Player(10000, "SomeRandomPlayerName");
Also, you read the int and the String in inverse order as you write them.

Create a List of generic list

How do I create a list of generic list? I have a Boxcar class that takes a generic argument and a Train class that is supposed to create a list of Boxcars. We are supposed to specify the type that will be in Boxcar in a separate main class, so until then boxcar has to stay generic. The following is the code that I have written. It compiles but in a separate driver class when calling the load method I get the error The method load(capture#1-of ?) in the type Boxcar<capture#1-of ?> is not applicable for the arguments (Person)
package proj5;
import java.util.ArrayList;
import java.util.List;
public class Train {
private List<Boxcar<?>> train;
private int maxSpeed;
private int minSpeed;
private String position;
private int numBoxcars;
private int maxNumBoxcars;
private int speed;
private String destination;
private boolean stopped = true;
public Train(int maxSpeed, int minSpeed, int maxNumBoxcars, String position){
train = new ArrayList<Boxcar<?>>();
this.maxSpeed = maxSpeed;
this.minSpeed = minSpeed;
this.maxNumBoxcars = maxNumBoxcars;
this.position = position;
}
public int getMaxNumBoxcars(){
return maxNumBoxcars;
}
public int getSpeed(){
return speed;
}
public String getPosition(){
return position;
}
public int getMaxSpeed(){
return maxSpeed;
}
public int getNumBoxcars(){
return numBoxcars;
}
public List<Boxcar<?>> getTrain(){
return train;
}
public void depart(String destination){
this.destination = destination;
speed = minSpeed;
stopped = false;
}
public void arrive(){
stopped = true;
position = destination;
}
public void addCar(Boxcar<?> boxcar, int i){
if(stopped){
boxcar.setMaxItems(i);
train.add(boxcar);
}
}
public void removeCar(int i){
if(stopped){
train.remove(i);
}
}
}
package proj5;
import java.util.ArrayList;
import java.util.List;
import java.util.Collections;
public class Boxcar<T extends Comparable<T>> {
private List<T> boxcar;
private int maxItems;
public Boxcar(){
boxcar = new ArrayList<T>();
}
public void load(T thing){
if(!boxcar.contains(thing) && boxcar.size() < maxItems){
boxcar.add(thing);
Collections.sort(boxcar);
}else{
}
}
public int getMaxItems(){
return maxItems;
}
public void setMaxItems(int i){
maxItems = i;
}
public void unload(T thing){
boxcar.remove(thing);
}
public List<T> getBoxcar(){
return boxcar;
}
}
I hope this better conveys what I am trying to accomplish
BoxCar which is a generic class:
class BoxCar<T>{
}
Train class which has a list of Boxcar:
class Train {
List<BoxCar<PassTheTypeHere>> = new ArrayList<BoxCar<PassTheTypeHere>>();
}
You need to supply a type in place of T and ? when creating a Generic List. For example a List of Boxcars containing Strings would look like this:
List<Boxcar<String>> train = new ArrayList<Boxcar<String>>();
The ? is an example of a wildcard, while a T represents a type that is referenced inside the source of List. That point can be tricky to understand without a deeper understanding of Generics, but I wanted to be sure address it for completeness sake. Take a look at this page for more information about how to use Generics inside your code.
Looking at your revised question, I would direct you to this line of code:
public class Boxcar<T extends Comparable<T>> {
and then just below it this line:
private List<T> boxcar;
This means whatever type you pass to new Boxcar<type>() will be carried over to the inner list (and other methods that expect an object of type T).
Based on the wording of your original question it sounds like you want to create a list of boxcars.
Below is all you would need to do.
private List<Boxcar> boxcarList = new ArrayList<Boxcar>();

Categories

Resources