How to save and load a HashMap<String,Object>? - java

HashMap
public Map<String, BarrackData> barrack = new HashMap<String, BarrackData>();
BarrackData.java
public class BarrackData {
int A;
int B;
int C;
int D;
int E;
String Title;
public BarrackData(int a, int b, int c, int d, int e, String title) {
A = a;
B = b;
C = c;
D = d;
P = p;
Title = title;
}
How can I save this HashMap?
And load it?
I tried different methodes with Objectin/outputstream,
it ended up with NotSerializable, ObjectSteam and IO exception,
Where i have no clue how to deal with them.

Only Serializable classes may be serialized: Just add implements Serializable to your class:
public class BarrackData implements Serializable {
Note that to actually be serialized, all fields within the class must be Serializable, however java primitives, arrays (if the element type is Serializable), java.lang classes (like String) and Collections (if the element type is Serializable) are Serializable, so you're OK.

To complete answers, pay attention to the fact that the outcome of keySet() belonging to HashMap (if you need it at any time) is not Serializable.
Indeed, keys aren't supposed to be dissociated from values concerning an HashMap.

You must make your Object class serializable (give it serialize() and deserialize() methods which convert it to/from a string or some such that can be saved/loaded). Apparently, HashMaps facilitate some level of serialization out of the box.
Here is a link to a tutorial on Java serialization: http://www.tutorialspoint.com/java/java_serialization.htm
and here is some more detailed info on HashMap serialization:
Serializing and deserializing a map with key as string
As Bohemian mentioned, implementing Serializable is the standard way to do this.

Related

How to implement compareTo for any types of comparable objects

I don’t know how I can compare 2 comparable objects without some other variable which tells me which is larger. The question is: Create a class called Max that provides a single class method called max. max takes two arguments to objects that can be compared—that is, that implement the Java Comparable interface as shown above. It returns a reference to whichever is larger. If the two objects are equal, you should return the first. How Comparable is implemented is up to each class, and your method will be called on multiple different kinds of objects.
It gives the int compareTo (Object other) method in the interface but I’m having trouble finding a solution.
public class Max implements Comparable
{
public int compareTo(Object other)
{
}
public static Comparable max(Comparable first, Comparable second)
{
int fi = first.compareTo(second);
if(fi >0)
return first;
else if (fi<0)
return second;
return first;
}
}
java.lang.AssertionError: Class should not implement Comparable: expected [false] but found [true]
That is one of the errors. But also I need help writing the compareTo method.
I deleted my previous answer because I think, imho, you are over complicating this. Since the two arguments to max have implemented the Comparable<T> interface, all you have to do is call it as:
int ret = first.compareTo(second);
Then return first or second like you are doing based on the value of ret. That way you don't need to know anything about how it was implemented. Perhaps you could get some clarification from either your instructor or someone else who is working on this (I presume it is for an assignment).
It would be worthwhile for you to create some test classes which implement the interface. You can just make up some variable that represents size.
The keyword for your question is generics. You might want to do some research and read something about it. Take a look at the following example. I've implemented the class Max as a static class to keep it simple:
import java.time.LocalDate;
public class MyTestClass{
public static void main(String args[]) {
Integer i = 16;
Integer j = 15;
Integer m = Max.max(i, j);
System.out.println(m);
String k = "aaaa";
String n = "zzzz";
String s = Max.max(k, n);
System.out.println(s);
LocalDate d = LocalDate.now();
LocalDate e = LocalDate.now().plusDays(2);
LocalDate f = Max.max(d , e);
System.out.println(f);
}
static class Max{
public static <T extends Comparable> T max(T first, T second) {
if (first.compareTo(second) >= 0)
return first;
else
return second;
}
}
}
As you can see, there is a class Max with a single method max which accepts two objects, for example two integers, two strings or two date objects.
Since all these classes implement the comparable interface, you can use the max method for all object types. The compiler then decides during the runtime which comapreTo method to call, that is the compareTo of the class Integer, String, LocalDate or whatever.

How can I cast objects that don't inherit each other?

I have 2 different classes with different fields and a class which has all the fields of both classes. Is there any way to cast the object in to two separate objects?
class A{
private int a;
private int b;
}
class B{
private int a;
private int b;
}
If object D have all the properties of A and B classes, Is there any way to cast them separately?
Casting take place from child to parent (downcast) or vise versa (upcast):
class A extends B
B b = (B)(new A());
or in case of interfaces:
List<String> myList = new ArrayList<>();
ArrayList<String> myArrayList = (ArrayList)myList;
Be careful when casting - if casting is not possible, you'll receive Exception!
In your case, mapping is what you're looking for. You simply need a mapper.
For example:
public class AToBMapper {
public static A fromB(B b) {
A a = new A();
a.setA(b.getA());
a.setB(b.getB());
return a;
}
public static B fromA(A a) {
//fill in
}
}
As complement of the very good answer of xenteros, you could also use library to do it if you have to repeat this task for many classes.
Spring, apache-commons and many others provides utility class to copy field by field which one of them that have the same name and type between two classes:
For example with ModelMapper :
ModelMapper mapper = new ModelMapper();
A a = new A(....);
B b = mapper.map(a, B.class)
Some libraries are very efficient (Selma, MapStruct, JMapper). Most of them generating the code at compile time
Others are less efficient.
You should so evaluate this point, the size of objects to map and the mapping frequency before generalizing the use of this kind of library.

Good way to change sort criteria for java class

I have a class representing a column. It has a comparator which looks something like this:
class Column
{
int xposition;
int usage;
#Override
public int compare(Object arg0, Object arg1)
{
// sort logic
}
}
I have a TreeSet of Columns. I want to sort the TreeSet first by x-position, and then at some point by usage.
What I tried is to create a superclass, such as Column2, that extends Column and has a different compare method. However that makes converting from Column to Column2 (or visa versa) very ugly. I also thought of a flag in the Column that indicates how to do the sort, but that would mean modifying all the objects in order to change the sort criteria.
Is there any better way to do this?
I would have the comparison logic in a set of external Comparators to represent the different sorting cases you have, and then create a new TreeSet when you want to change the sort:
class Column
{
int xposition;
int usage;
public static final Comparator<Column> SortByX = new Comparator<Column>() {
#Override
public int compare(Column c1, Column c2)
{
return Integer.compare(c1.xposition, c2.xposition);
}
};
public static final Comparator<Column> SortByUsage = new Comparator<Column>() {
#Override
public int compare(Column c1, Column c2)
{
return Integer.compare(c1.usage, c2.usage);
}
};
}
TreeSet<Column> cols = new TreeSet<>(Column.SortByX);
Then, to change the sort:
TreeSet<Column> updated = new TreeSet<>(Column.SortByUsage);
updated.addAll(cols);
cols = updated;
With appropriate synchronization if this is happening in a multi-threaded environment.
Whatever you do, do not change the behavior of an object's Comparator using mutable state. If you do, you could easily "lose track" of an object after it has been put into a collection like TreeSet.
Strategy pattern
What you want to achieve seems a classic use case for the Strategy pattern (e.g. Real World Example of the Strategy Pattern)
In essence, you want to package up this comparison function into something that you can put in a separate field for your column class - a plain class with that single function that implements Comparable would work. Then, your column would just delegate the call to whatever comparator is stored in that field.
This is exact use case of Guava's ComparisionChain:
Example taken from here :
public int compareTo(Foo that) {
return ComparisonChain.start()
.compare(this.xposition, that.xposition)
.compare(this.usage, that.usage)
.result();
}
Like Sean Bright answer, I'd use external Comparator and if you are working with Java 8, you can do it pretty easily:
public static final Comparator<Foobar> NAME_THEN_AGE =
Comparators.comparing(Foobar::getName, String.CASE_INSENSITIVE_ORDER)
.thenComparing(Foobar::getAge)
;
....
TreeSet<Foobar> foobar = new TreeSet<>(NAME_THEN_AGE);
However, better remaindered that not, it is generally a bad idea to override Comparable on a child class - perhaps it should be final on the parent or one should create a protected compareTo0(A) doing the common work (to avoid comparing object by their parent class).
There are reason for that, and one such is the following (from the Javadoc of Comparable.compareTo):
The implementor must ensure sgn(x.compareTo(y)) ==
-sgn(y.compareTo(x)) for all x and y. (This implies that x.compareTo(y) must throw an exception iff y.compareTo(x) throws an
exception.)
Let's say you have class B and C extending A and A implements Comparable<A>:
class A implements Comparable<A> {
#Override
public int compareTo(A other) {return ...;}
}
class B extends A {
#Override
public int compareTo(A other) {return compareToAsB(((B)other));}
}
class C extends A {
#Override
public int compareTo(A other) {return compareToAsC(((C)other));}
}
It does not really matter what A::compareTo returns. Neither what compareToAsB and compareToAsC does.
The problem is however here:
A a = ...;
B b = ...;
C c = ...;
a.compareTo(b); // ok
a.compareTo(c); // ok
b.compareTo(a); // ko ClassCastException
b.compareTo(c); // ko ClassCastException
c.compareTo(a); // ko ClassCastException
c.compareTo(b); // ko ClassCastException
As quoted in the javadoc, a.compareTo(b) should throw a ClassCastException.
Also, there are part in the Java code (Collections.sort) where it is important to ensure that sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) for all x and y.

How to implement efficient hashcode for a wrapper object in Java?

Let's say I have the following class A that implements an interface M:
class A implements M {
int i;
int hashCode() { return i; }
}
And a wrapper for A, for example
class AWrapper implements M {
A a;
public Wrapper(A a) {
this.a = a;
}
int hashCode() { ??? }
}
This hierarchy is a sort of Composite Pattern. My question is what is a good hashcode for the AWrapper class? I can use a.hashCode(), but then all A's and
AWrapper's will have the same hashcode. What is the best way to implement such a hash code?
As some people ask what's the rationale behind this design, let me make it more concrete. I'm writing a data type for regular expressions. So A is a symbol, and there are regular operators such as *, +, ? that are essentially wrappers of symbols, e.g., Star(A). I also want to make sure there is only one instance of an object, that's why I need sharing, so if someone writes:
r1 = a*a
r2 = a*c
represented by Seq(Star('a'), 'a') and Seq(Star('a'), 'c'), I want two instances of Star('a') be shared, of course via a factory call.
Putting As and AWrappers as keys in the same map does not sound right. But if that's what you want you could use Objects.hash(a).
When a single object reference is supplied, the returned value does not equal the hash code of that object reference.
As a side note, if AWrapper is immutable and the hashCode method is called often and A::hashCode is not trivial and memory footprint is not an issue, you may want to precalculate the hashcode (worth testing if it is worth it in your scenario):
class AWrapper implements M {
private final A a;
private final int hash;
public Wrapper(A a) {
this.a = a;
hash = Objects.hash(a);
}
int hashCode() { return hash; }
}

Serious generics issue: int vs. Integer java

for a long while, i have been trying to get a piece of code to work, and it just is not possible. the class i have requires a generic which i have set to Integer. so i tried the follwoing:
public class a<T> //set generics for this function
{
private T A;
protected boolean d;
public a(final T A)
{
this.A = A;
//do calculations
//since constructor cannot return a value, pass to another function.
this.d = retnData(Integer.parseInt(A.toString()) != 100); //convert to an integer, the backwards way.
}
private boolean retnData(boolean test)
{
return test;
}
}
// IN ANOTHER CLASS
transient a<Integer> b;
boolean c = b.d = b.a(25); // throws an erorr: (Int) is not apporpriate for a<Integer>.a
Java will not allow this since java sees that int != Integer, even though both accept the same data. and because of the way generics works i cannot set a b; because of the primitiveness of the type int. Even casting to an Integer does not work, as it still throws the "type error"
finnaly, i have to ask if there is some sort of work around for this, or is it futile to try and get this to work?
You are trying to explicitly call a constructor as an instance method. This cannot be done in Java.
Perhaps you want:
transient a<Integer> b = new a<Integer>(25);
boolean c = b.d;
However, since d is declared to be protected, that will only work if this code is in another class derived from a or in the same package.
Use
final a<Integer> b = new a<Integer>(10);
boolean c = b.d;
int can be explicitly converted to Integer with new Integer(10) or Integer.valueOf(10)
The code does not make much sense: b is an object of type a, which does not have an a method - so not sure what you expect from b.a(25);... This has nothing to do with int vs Integer...

Categories