Taming immutable data pipeline verboseness - java

I have a CSV conversion class. It's job is to muck with values and produce few outputs. The CSV row has around 30 columns. I've modelled via immutable objects:
In(i1, i2, ..., iM)
OutA(a1, a2, ..., aN)
OutB(b1, b2, ..., bO)
...
OutK(k1, k2, ..., kP)
OutX(x1, x2, ..., xQ)
There are inter-dependencies: b1 is the same as a1, b2 is calculated based on a2, they combine to the final result (OutX). Some calculations are expensive.
The end result is a huge method that looks similar to this simplified monster:
OutX method(In in) {
I1 i1 = in.getI1();
I1 i2 = in.getI2();
...
I1 iM = in.getIM();
A1 a1 = fa1(i1, i2);
A2 a2 = fa2(i2, i5, iM);
...
AN aN = ...;
OutA outA = new OutA(
a1,
a2,
...,
aN);
A1 b1 = a1;
B2 b2 = fb2(a2, i5, i13);
...
BO bO = ...;
OutB outB = new OutB(
b1,
b2,
...,
bO);
...
return new OutX(
outA,
outB,
...,
outK);
}
'Tis wonderful being immutable and type-checked and stuff. 'Tis also 300 lines and this is for each "flavor" of CSV. Ugh. Breaking up just creates methods that are mostly parameters + constructor calls.
Are there patterns or libraries to un-Frankenstein this?

The Adapter pattern might be helpful. Each layer/shell delegates as much as possible to build up to the final result. Here's an example:
public class App {
public static void main(String[] args) {
App app = new App();
app.process();
}
private void process() {
In in = new In(1, 2, 3);
OutA a = new OutA(in);
OutB b = new OutB(a);
System.out.println(b);
}
public class In {
private final int i1;
private final int i2;
private final int i3;
public In(int i1, int i2, int i3) {
this.i1 = i1;
this.i2 = i2;
this.i3 = i3;
}
public int getI1() {
return i1;
}
public int getI2() {
return i2;
}
public int getI3() {
return i3;
}
}
public class OutA {
private final In in;
private Integer a3;
public OutA(In in) {
this.in = in;
}
public int getA1() {
return in.getI1();
}
public int getA2() {
return in.getI2() * 2;
}
public int getA3() {
if (a3 == null) {
// a3 = some expensive calculation
a3 = 1; // hold the value to avoid expensive calculation next time method is called
}
return a3;
}
}
public class OutB {
private final OutA a;
public OutB(OutA a) {
this.a = a;
}
public int getB1() {
return a.getA1();
}
public int getB2() {
// a.getA3() is expensive, but only the first time it's called
return a.getA3() + 4;
}
public int getB3() {
// a.getA3() is expensive, but only the first time it's called
return a.getA3() + 9;
}
public String toString() {
return "b1: " + getB1() + " b2: " + getB2() + " b3: " + getB3();
}
}
}
Output: b1: 1 b2: 5 b3: 10
UPDATE: here's a more interesting example using a factory to have different calculations, but still using the same interface.
public class App {
public static void main(String[] args) {
App app = new App();
app.process();
}
private void process() {
In in = new In(1, 2, 3);
OutXFactory factory = new OutXFactory();
OutX resultType1 = factory.create(in, CSVType.TYPE_1);
System.out.println(resultType1);
OutX resultType2 = factory.create(in, CSVType.TYPE_2);
System.out.println(resultType2);
}
public class In {
private final int i1;
private final int i2;
private final int i3;
public In(int i1, int i2, int i3) {
this.i1 = i1;
this.i2 = i2;
this.i3 = i3;
}
public int getI1() {
return i1;
}
public int getI2() {
return i2;
}
public int getI3() {
return i3;
}
}
public enum CSVType {
TYPE_1, TYPE_2;
}
public class OutA {
private final In in;
private Integer a3;
public OutA(In in) {
this.in = in;
}
public int getA1() {
return in.getI1();
}
public int getA2() {
return in.getI2() * 2;
}
public int getA3() {
if (a3 == null) {
// a3 = some expensive calculation
a3 = 1; // hold the value to avoid expensive calculation next time method is called
}
return a3;
}
}
public class OutB {
private final OutA a;
public OutB(OutA a) {
this.a = a;
}
public int getB1() {
return a.getA1();
}
public int getB2() {
// a.getA3() is expensive, but only the first time it's called
return a.getA3() + 4;
}
public int getB3() {
// a.getA3() is expensive, but only the first time it's called
return a.getA3() + 9;
}
}
public interface OutX {
public int getX1();
public int getX2();
public int getX3();
}
public abstract class AbstractOutX implements OutX {
#Override
public String toString() {
return "x1: " + getX1() + " x2: " + getX2() + " x3: " + getX3();
}
}
public class OutXA extends AbstractOutX {
private final OutA a;
public OutXA(OutA a) {
this.a = a;
}
#Override
public int getX1() {
return a.getA1() + 1;
}
#Override
public int getX2() {
return a.getA2() + a.getA3() + 2;
}
#Override
public int getX3() {
return a.getA1() + a.getA2() + 3;
}
}
public class OutXAB extends AbstractOutX {
private final OutA a;
private final OutB b;
public OutXAB(OutA a, OutB b) {
this.a = a;
this.b = b;
}
#Override
public int getX1() {
return a.getA1() + b.getB1();
}
#Override
public int getX2() {
return a.getA2() * b.getB2();
}
#Override
public int getX3() {
return (int) Math.pow(a.getA3(), b.getB3());
}
}
public class OutXFactory {
public OutX create(In in, CSVType type) {
if (type == CSVType.TYPE_1) {
OutA a = new OutA(in);
return new OutXA(a);
} else {
OutA a = new OutA(in);
OutB b = new OutB(a);
return new OutXAB(a, b);
}
}
}
}

Related

Processing and conversion of advanced json string to java objects

I know that conversion of JSON string to JAVA object using Jackson object mapper package.
Suppose if I have advanced Json string like what I mentioned below. Is it possible to convert that as a Java object?
{
"a": 123123,
"b":true,
"cList":[{
"c1": "valuec1",
"c2": "valuec2",
"c3": "valuec3"
},
{
"c1": "valuec4",
"c2": "valuec5",
"c3": "valuec6"
}]
}
public class Codebeautify {
private float a;
private boolean b;
ArrayList < Object > cList = new ArrayList < Object > ();
// Getter Methods
public float getA() {
return a;
}
public boolean getB() {
return b;
}
// Setter Methods
public void setA(float a) {
this.a = a;
}
public void setB(boolean b) {
this.b = b;
}
}
class Example {
public int a;
public boolean b;
public List<Exmaple1> cList;
#Override
public String toString() {
return "Example [a=" + a + ", flag=" + b + ", e1=" + cList + "]";
}
}
class Exmaple1 {
public String c1;
public String c2;
public String c3;
public String getC1() {
return c1;
}
public void setC1(String c1) {
this.c1 = c1;
}
public String getC2() {
return c2;
}
public void setC2(String c2) {
this.c2 = c2;
}
public String getC3() {
return c3;
}
public void setC3(String c3) {
this.c3 = c3;
}
}
class B {
public String c1;
public String c2;
public String c3;
public B() {}
public B(String c1, String c2, String c3) {
this.c1 = c1;
this.c2 = c2;
this.c3 = c3;
}
#Override
public String toString() {
return "{" +
" c1 :'" + c1 + '\'' +
", c2 :'" + c2 + '\'' +
", c3 :'" + c3 + '\'' +
'}';
}
public String getC1() {return c1;}
public void setC1(String c1) {this.c1 = c1;}
public String getC2() {return c2;}
public void setC2(String c2) {this.c2 = c2;}
public String getC3() {return c3;}
public void setC3(String c3) {this.c3 = c3;}
}
public class C {
public int a;
public boolean b;
public List<B> cList;
public C() {}
public C(int a, boolean b, List<B> cList) {
this.a = a;
this.b = b;
this.cList = cList;
}
#Override
public String toString() {
return "{" +
" a :" + a +
", b :" + b +
", cList :" + cList +
'}';
}
public int getA() {return a;}
public void setA(int a) {this.a = a;}
public boolean isB() {return b;}
public void setB(boolean b) {this.b = b;}
public List<B> getcList() {return cList;}
public void setcList(List<B> cList) {this.cList = cList;}
public static void main(String[] args) {
List<B> cList = new ArrayList<>();
cList.add(new B("x1", "x2", "x3"));
cList.add(new B("y1", "y2", "y3"));
C obj = new C(123, true, cList);
ObjectMapper objectMapper = new ObjectMapper();
// obj --> json
String json = null;
try {
json = objectMapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
System.out.println(json == null ? "error" : json);
// json1 --> obj1
//String json1 = "{\"a\":123,\"b\":true,\"cList\":[{\"c1\":\"x1\",\"c2\":\"x2\",\"c3\":\"x3\"},{\"c1\":\"y1\",\"c2\":\"y2\",\"c3\":\"y3\"}]}";
String json1 = json;
C obj1 = null;
try {
obj1 = objectMapper.readValue(json1, C.class);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(obj1 == null ? "error" : obj1);
}
}

How to find a maximum value of an index in a list of lists

I have a list of lists of objects, with each single innerlist having 3 Object elements, theoretically a String and two doubles,say a and b, in that order.
ArrayList<ArrayList<Object>> timings = new ArrayList<ArrayList<String>>()
for (int runnerno = 0; runnerno < runners; runnerno++) {
ArrayList<Object> thisrunner = new ArrayList<Object>();
thisrunner.add(sc.next()); //string
thisrunner.add(sc.nextDouble()); //double a
thisrunner.add(sc.nextDouble()); //double b
timings.add(thisrunner);
sc.nextLine();
}
How do I find out the maximum a value in my list of lists? ie. I want to find an indexed maximum.
1) Lets make a better encapsulation of your data object, call it FooBar
public class FooBar {
private String text;
private Double x;
private Double y;
public FooBar() {
}
public FooBar(String text,Double x,Double y) {
this.text = text;
this.x = x;
this.y = y;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Double getX() {
return x;
}
public void setX(Double x) {
this.x = x;
}
public Double getY() {
return y;
}
public void setY(Double y) {
this.y = y;
}
}
2) Populate a list of FooBars
List<FooBar> points = new ArrayList<FooBar>();
for( int i = 0; i < 1000; i++ ) {
FooBar f = new FooBar("Text" + i,
ThreadLocalRandom.current().nextDouble(0, 100),
ThreadLocalRandom.current().nextDouble(0, 100));
points.add(f);
}
3) Use streams.max (with Comparator)
Optional<FooBar> maxFooBar = points.stream().max(new Comparator<FooBar>() {
#Override
public int compare(FooBar o1, FooBar o2) {
return o1.getX().compareTo(o2.getX());
}
});
System.out.println("Max Point: " + maxFooBar.get().getX());
4) Or use Collections.max
FooBar maxFooBar = Collections.max(points, new Comparator<FooBar>() {
#Override
public int compare(FooBar o1, FooBar o2) {
return o1.getX().compareTo(o2.getX());
}
});
System.out.println("Max Point: " + maxFooBar.getX());
5) Or just sort the list yourself and get the first item (if sorted Descending; get last if Ascending)
points.sort(new Comparator<FooBar>() {
#Override
public int compare(FooBar o1, FooBar o2) {
return -1 * o1.getX().compareTo(o2.getX());
}
});
System.out.println("Max Point: " + points.get(0).getX());
The maximum double value of all values that are of type Double in the list of lists, like so
public static double findMax(List<List> lists) {
double max = Double.MIN_VALUE;
for (List list : lists)
for (Object o : list)
if (o instanceof Double)
if ((Double) o).doubleValue() > max)
max = ((Double) o).doubleValue();
return max;
}
what if you use Comparator interface for sorting your each individual Runner object in ascending order and the last Runner object inside timings treeSet would be always the index of maximum value
we cannot use the ArrayList since it does not have any constructor which support Comparator as an argument
public class Runner {
private String s;
public double a;
public double b;
public Runner() {}
public Runner(String s, double a, double b) {
this.s = s;
this.a = a;
this.b = b;
}
#Override
public String toString() {
return s + " " + a + " " + b;
}
}
calling class
import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;
public class Calling {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int runners = 3;
TreeSet<Runner> timings = new TreeSet<>(new MyComparator());
for (int runnerno = 0; runnerno < runners; runnerno++) {
timings.add(new Runner(sc.nextLine(), Double.parseDouble(sc.nextLine()), Double.parseDouble(sc.nextLine())));
}
System.out.println(timings);
System.out.println("max value " + timings.last());
}
}
class MyComparator implements Comparator<Runner> {
#Override
public int compare(Runner o1, Runner o2) {
return Double.valueOf(o1.a).compareTo(Double.valueOf(o2.a));
}
}

Is it possible to get public static field from template class argument?

Given
class A {
public static A newInstance(int x) { ... }
}
And several classes containing static fields of type A
class B1 {
public static A MIN = A.newInstance(10);
}
class B2 {
public static A MIN = A.newInstance(15);
}
I would like to parameterize a class with B1 or B2 to get MIN field of type A from class B in the class C:
class C <T, P> {
private T t = ???;
}
When C<A, B1> c = new C(); what should be placed instead ??? to get B1.MIN?
Is it possible?
EDIT:
Thank you for the answers, I have upvoted both.
I have arrived simply at
class C <T, P> {
private T t;
public C(T min) {
this.t = min;
}
}
This will be just C<A, B1> c = new C<A, B1>(B1.MIN); because as you can see it is hard to avoid a constructor for C taking an instance of B1 or smth like that. But in this case B1 at least not instantiated.
You can use an interface to achieve this behavior:
class A {
public static A newInstance() { return new A(); }
}
interface HasMin {
public static A MIN = null;
}
class B1 implements HasMin {
public static A MIN = A.newInstance();
}
class B2 implements HasMin {
public static A MIN = A.newInstance();
}
class C<T extends HasMin> {
private A t = T.MIN;
}
Then you can create: C<B1> and C<B2> and use both.
As Tom suggested in the comments below, this approach is limited to use static fields. An even better approach would be:
public class Play {
public static void main(String[] args) {
B1 b1 = new B1();
C<B1> c = new C<>(b1);
System.out.println(c.getA()); // prints: A{ x=10 }
B2 b2 = new B2();
C<B2> c2 = new C<>(b2);
System.out.println(c2.getA()); // prints: A{ x=20 }
}
}
class A {
private int x;
public A(int x) {
this.x = x;
}
#Override
public String toString() {
return "A{ x=" + x + " }";
}
public static A newInstance(int x) {
return new A(x);
}
}
interface GetMin {
public A getMin();
}
class B1 implements GetMin {
public A MIN = A.newInstance(10);
#Override
public A getMin() {
return MIN;
}
}
class B2 implements GetMin {
public A MIN = A.newInstance(20);
#Override
public A getMin() {
return MIN;
}
}
class C<T extends GetMin> {
private A a = null;
public C(T t) {
a = t.getMin();
}
public A getA() {
return a;
}
}
I would forget static and have a concrete instance of an interface:
public interface Bounds<T> {
T min();
}
The concrete instance could be singleton, so next best thing to a static:
public enum B implements Bounds<A> {
INSTANCE;
private final A min = A.newInstance(10);
#Override
public A min() {
return min;
}
}
C then defined like so:
public class C<T, P extends Bounds<T>> {
private T min;
public C(P bounds) {
min = bounds.min();
}
public T getMin() {
return min;
}
}
Usage:
C<A, B> c = new C(B.INSTANCE);
Self describing
Maybe you don't want this meta data type (B), maybe you want types to describe themselves. So C could be defined for types that can describe their own bounds:
public class C<T extends Bounds<T>> {
private T min;
public C(T anyT) {
min = anyT.min();
}
public T getMin() {
return min;
}
}
Usage:
C<A> c = new C(A.zero); //any A will do
Where A is:
public class A implements Bounds<A>{
public final static A zero = A.newInstance(0);
private final static A min = A.newInstance(10);
public static A newInstance(int x) {
return new A(x);
}
private int x;
public A(int x) {
this.x = x;
}
#Override
public A min() {
return min;
}
}

Keep getting "null has 00null"

Im working with a stand-alone class, and a main driver, here's the stand-alone class:
public class Bugs{
private String bugType;
private int legs;
private int arms;
private String nativeTo;
public Bugs(String bt, int l, int a, String nt){
bt=bugType;
l=legs;
a=arms;
nt=nativeTo;
}
public Bugs(String bt, int l, int a){
bt=bugType;
l=legs;
a=arms;
nativeTo="Not known";
}
public String getbt(){
return bugType;
}
public void setbugType(String bugType){
this.bugType=bugType;
}
public int getlegs(){
return legs;
}
public void setlegs(int legs){
this.legs=legs;
}
public int getarms(){
return arms;
}
public void setarms(int arms){
this.arms=arms;
}
public String getnativeTo(){
return nativeTo;
}
public void setnativeTo(String nativeTo){
this.nativeTo=nativeTo;
}
public String toString(){
return bugType + " has " + legs + arms + nativeTo;
}
}
And here's the main driver:
public class myBugs{
public static void main (String args[]){
Bugs asiaBeetle = new Bugs("Asian Beetle", 2, 2, "Japan");
Bugs spider = new Bugs("Spider", 1000, 0);
Bugs americanBeetle = new Bugs("American Beetle", 2, 2, "USA");
System.out.println(asiaBeetle);
}
}
JGRASP keeps returning "null has 00null", every time I run the main driver. What am I doing wrong?
Swap your assignments in your constructors :
public Bugs(String bt, int l, int a, String nt){
bugType = bt;
legs = l;
arms = a;
nativeTo = nt;
}
You have to do the same for the other :
public Bugs(String bt, int l, int a){
bugType = bt;
legs = l;
arms = a;
nativeTo="Not known";
}
Change your constructor to this offcourse do the same for the other as well
public Bugs(String bt, int l, int a, String nt){
bugType=bt;
legs=l;
arms=a;
nativeTo= nt;
}

static methods or setter or getters?

public class Operations {
private int add;
private int sub;
private int mul;
private int div;
private double sqrt;
public void setadd(int a, int b) {
add = a + b;
}
public void setsub(int a, int b) {
sub = a - b;
}
public void setmul(int a, int b) {
mul = a * b;
}
public void setdiv(int a, int b) {
div = a / b;
}
public void setsqrt(double sqt) {
sqrt = Math.sqrt(sqt);
}
public int getadd() {
return add;
}
public int getsub() {
return sub;
}
public int getmul() {
return mul;
}
public int getdiv() {
return div;
}
public double getsqrt() {
return sqrt;
}
}
Do I have to do a prototype of this or in Java that's not necessary, also how do I use static methods here instead of setter and getter.. I'm trying to do a calculator.. Are my methods ok?
Make all the operations (addition, multiplication, division, etc ) static methods of a Calculator class:
class Calculator{
public static int add(int a, int b){
return a+b;
}
...
I don't really understand the point of setting and getting, why not have your calculator like this:
public class Calculator {
public int add(int a, int b){
return a + b;
}
public int sub(int a , int b){
return a - b;
}
public int mul(int a, int b){
return a * b;
}
public int div(int a, int b){
return a/b;
}
public double sqrt(double sqt){
return Math.sqrt(sqt);
}
Your methods are all wrong, because you modeled your operation incorrectly. It is not supposed to contain its result, and it should do only one operation, not all of them. Operation object should be immutable, and it should produce an answer to a specific operation given two operands. You should separate binary operations from unary as well.
interface BinaryOp {
double calculate(double left, double right);
}
interface UnaryOp {
double calculate(double operand);
}
private static final BinaryOp ADD = new BinaryOp() {
double calculate(double left, double right) {
return left + right;
}
};
private static final BinaryOp SUB = new BinaryOp() {
double calculate(double left, double right) {
return left - right;
}
};
private static final BinaryOp MUL = new BinaryOp() {
double calculate(double left, double right) {
return left * right;
}
};
private static final BinaryOp DIV = new BinaryOp() {
double calculate(double left, double right) {
return left / right;
}
};
private static final UnaryOp SQRT = new UnaryOp() {
double calculate(double operand) {
return Math.sqrt(operand);
}
};
Now you can organize your operators by name:
private static final Map<String,BinaryOp> opByName = new HashMap<String,BinaryOp>();
static {
opByName.put("+", ADD);
opByName.put("-", SUB);
opByName.put("*", MUL);
opByName.put("/", DIV);
}
With this map, you can use your operations to perform calculations for you:
String op = "+";
double left = 123;
double right = 456;
double res = opByName.get(op).calculate(left, right);
Just to answer the part of the question not answered yet:
You do not need prototypes in java.
This looks like a good use for an enum or two:
enum BinOp {
ADD {
#Override
public int eval(int leftArg, int rightArg) {
return leftArg + rightArg;
}
#Override
public String symbol() {
return "+";
}
},
SUBTRACT {
#Override
public int eval(int leftArg, int rightArg) {
return leftArg - rightArg;
}
#Override
public String symbol() {
return "-";
}
}
// etc.
;
public abstract int eval(int leftArg, int rightArg);
public abstract String symbol();
}
And a similar enum for unary operators (only SQRT, at the moment).
You could use these as follows:
int left = 3;
int right = 2;
for (BinOp op : BinOp.values()) {
System.out.println("The value of "
+ left + " " + op.symbol() + " " + right " is "
+ op.eval(left, right)
);
}

Categories