I have a class as below:
public class Class2 {
private final Integer x;
private final Integer y;
public Class2(final Integer x, Integer y) {
this.x = x;
this.y = y;
}
public Integer getX() {
return x;
}
public Integer getY() {
return y;
}
}
I have a Map object like below:
Map<MyEnum , List<Class2>> mapX
I want to find the sum of x & y members of the Class2 instances in the List instance which is the value item in the above map. I want to use lambda expressions
I have come up with the following incomplete lambda. Thanks in advance.
mapX.entrySet().forEach(entry -> {
System.out.println("MapX-Key : " + entry.getKey() + "\nMapX-Value : "
+ entry.getValue().stream().collect(Collectors.summingInt(???)));
});
Not quite sure about what you're asking but one of these should help:
// Using Class2
Map<MyEnum , List<Class2>> mapX = null;
mapX.entrySet().forEach(entry -> {
System.out.println("MapX-Key : " + entry.getKey() + "\nMapX-Value : "
+ entry.getValue().stream()
.collect(Collectors.summingInt(x -> x.getX() + x.getY())));
});
// Values from Class2 via Class1
Map<MyEnum , List<Class1>> map1 = null;
map1.entrySet().forEach(entry -> {
System.out.println("MapX-Key : " + entry.getKey() + "\nMapX-Value : "
+ entry.getValue().stream()
.collect(Collectors.summingInt(x -> x.getClass2().getX() + x.getClass2().getY())));
});
You can go this way :
mapX.entrySet().stream()
.map(entry -> "MapX-Key : " + entry.getKey()
+ "\nMapX-Value : "
+ entry.getValue().stream().mapToInt(e -> e.getX() + e.getY()))
.forEach(System.out::println);
This will iterate over each Entry, then (map) create a String with the key, and then the sum of x and y, and at the end print them
Related
I'm trying to implement L-system as functions. For example, dragon curve looks like this:
static String F(int n) {
return n == 0 ? "F" : F(n - 1) + "+" + G(n -1);
}
static String G(int n) {
return n == 0 ? "G" : F(n - 1) + "-" + G(n -1);
}
#Test
void testDragonCurveAsStaticFunction() {
assertEquals("F", F(0));
assertEquals("F+G", F(1));
assertEquals("F+G+F-G", F(2));
assertEquals("F+G+F-G+F+G-F-G", F(3));
}
I want to implement this with lambda functions. I got the following implementation by referring to recursion - Implement recursive lambda function using Java 8 - Stack Overflow.
#Test
void testDragonCurveAsLambdaFunction() {
interface IntStr { String apply(int i); }
IntStr[] f = new IntStr[2];
f[0] = n -> n == 0 ? "F" : f[0].apply(n - 1) + "+" + f[1].apply(n - 1);
f[1] = n -> n == 0 ? "G" : f[0].apply(n - 1) + "-" + f[1].apply(n - 1);
assertEquals("F", f[0].apply(0));
assertEquals("F+G", f[0].apply(1));
assertEquals("F+G+F-G", f[0].apply(2));
assertEquals("F+G+F-G+F+G-F-G", f[0].apply(3));
}
Is there a way to implement this without using an array?
But I want to create a generic L-System, so I don't want to define a new class, interface or method for the dragon curve.
I found a solution that uses Map.
#FunctionalInterface
interface IntStr {
String apply(int n);
static IntStr cond(String then, IntStr... otherwise) {
return n -> n == 0 ? then
: Stream.of(otherwise)
.map(f -> f.apply(n - 1))
.collect(Collectors.joining());
}
static IntStr constant(String string) {
return n -> string;
}
static IntStr call(Map<String, IntStr> map, String functionName) {
return n -> map.get(functionName).apply(n);
}
}
and
#Test
void testDragonCurveAsLambda() {
Map<String, IntStr> map = new HashMap<>();
map.put("F", IntStr.cond("F",
IntStr.call(map, "F"),
IntStr.constant("+"),
IntStr.call(map, "G")));
map.put("G", IntStr.cond("G",
IntStr.call(map, "F"),
IntStr.constant("-"),
IntStr.call(map, "G")));
IntStr f = map.get("F");
assertEquals("F", f.apply(0));
assertEquals("F+G", f.apply(1));
assertEquals("F+G+F-G", f.apply(2));
assertEquals("F+G+F-G+F+G-F-G", f.apply(3));
}
I tried implementing it using a class combining two IntStr fields set via constructor or setters:
interface IntStr {
String apply(Integer i);
}
class Recursive {
IntStr other;
IntStr curr;
public Recursive() {}
public Recursive(String p1, String s1, String p2, String s2) {
this.curr = n -> n == 0 ? p1 : curr.apply(n - 1) + s1 + other.apply(n - 1);
this.other = n -> n == 0 ? p2 : curr.apply(n - 1) + s2 + other.apply(n - 1);
}
public void setCurr(String p, String s) {
this.curr = n -> n == 0 ? p : curr.apply(n - 1) + s + other.apply(n - 1);
}
public void setOther(String p, String s) {
this.other = n -> n == 0 ? p : curr.apply(n - 1) + s + other.apply(n - 1);
}
}
Then the following code succeeded:
void testDragonCurveAsLambdaFunction() {
Recursive f1 = new Recursive("F", "+", "G", "-");
// or using setters
// f1.setCurr("F", "+");
// f1.setOther("G", "-");
assertEquals("F", f1.curr.apply(0));
assertEquals("F+G", f1.curr.apply(1));
assertEquals("F+G+F-G", f1.curr.apply(2));
assertEquals("F+G+F-G+F+G-F-G", f1.curr.apply(3));
}
An example using AtomicReference as a container for IntStr reference without creating Recursive class:
void testDragonCurveAsLambdaFunction() {
AtomicReference<IntStr>
curr = new AtomicReference<>(),
other = new AtomicReference<>();
curr.set(n -> n == 0 ? "F" : curr.get().apply(n - 1) + "+" + other.get().apply(n - 1));
other.set(n -> n == 0 ? "G" : curr.get().apply(n - 1) + "-" + other.get().apply(n - 1));
assertEquals("F", curr.get().apply(0));
assertEquals("F+G", curr.get().apply(1));
assertEquals("F+G+F-G", curr.get().apply(2));
assertEquals("F+G+F-G+F+G-F-G", curr.get().apply(3));
}
public CompletableFuture<String> description() {
CompletableFuture<String> result = CompletableFuture
.supplyAsync(() -> "Search for: " + this.stop + " <-> " + name + ":\n")
.thenApply(x -> x += "From " + this.stop + "\n");
CompletableFuture<Void> temp = services.thenAccept(x -> {
for (BusService service : x.keySet()) {
CompletableFuture<Set<BusStop>> stops = x.get(service);
result = result.thenApply(y -> y += describeService(service, stops));
}
});
return result;
}
public CompletableFuture<String> describeService(BusService service,
CompletableFuture<Set<BusStop>> stops) {
return stops.thenApply(x -> {
if (x.isEmpty()) {
return "";
}
return x.stream()
.filter(stop -> stop != this.stop)
.reduce("- Can take " + service + " to:\n",
(str, stop) -> str += " - " + stop + "\n",
(str1, str2) -> str1 + str2);
});
}
I was trying to update the result in the forloop in description(), since result.thenApply() results in a new CompletableFuture instance, I need to reassign it to a new variable in order to update result, but i am not very sure how
You don't need to reassign it to a new variable, and you shouldn't. Combine the futures instead.
return services.thenCombine(result, (x, y) -> {
for (BusService service : x.keySet()) {
CompletableFuture<Set<BusStop>> stops = x.get(service);
y += describeService(service, stops);
}
return y;
});
I have a object
Class DummyObject() {
double first;
double second;
double third;
double fourth;
}
Class SomeObject() {
List<DummyObject> objectList;
}
Class HighestObject() {
List<SomeObject> objectList;
}
A variable of type SomeObject is given. I have to find out if sum of four field in DummyObject is not getting equal to amount X.
using for loop, It can easily be written like:
for(SomeObject someObject : hightestObject.getObjectList()) {
for(DummyObject dummyObject : someObject.getObjectList()){
if((dummyObject.first + dummyObject.second + dummyObject.third + dummyObject.fourth) != X) {
return false;
}
}
}
How can we do it using java stream ?
You could combine flatMap and anyMatch:
HighestObject h = ...;
boolean foundNotX = h.getObjectList().stream() //Stream<SomeObject>
.flatMap(so -> so.getObjectList().stream()) //Stream<DummyObject>
.mapToDouble(o -> o.first + o.second + o.third + o.fourth) //DoubleStream
.anyMatch(sum -> sum != X);
if (foundNotX) return false;
Depending on what you are after, using .allMatch(sum -> sum == X) might be more appropriate.
Try this.
return hightestObject.getObjectList().stream()
.flatMap(someObject -> someObject.getObjectList().stream())
.allMatch(dummyObject ->
dummyObject.first + dummyObject.second + dummyObject.third + dummyObject.fourth == X);
I understand Java passes everything by value including references. Since the called function has copies of formal parameter objects--copies of references--it cannot modify the original object using the default assignment operator(=). And I am assuming that a reference is equivalent to a pointer in C--it holds the address of the actual object variable.
Edit: Also even though other questions have asked similar questions, I was trying to see if I could overload the assignment operator to make the swap work using assignment operator--learned that Java does not support user-defined operator overloading. Also, I was hoping someone could offer a new way of making it work.
Here is a class I made to test this notion and see if I can get the actual object outside of the object's declared scope.
public class Time {
public int currentTime = 0;
public static int iD =0 ;
public final int uniqueObjId = iD;
public Time(int settingTime) {
currentTime = settingTime;
iD++;
}
public int getTime() {
return currentTime;
}
public static long getCurrTime() {
return System.currentTimeMillis();
}
public void setTime(int currentTime) {
this.currentTime = currentTime;
}
public static void main(String[] args) {
Time t1 = new Time(100);
Time t2 = new Time(200);
System.out.println("Before testInt is " + t1.getTime());
System.out.println("Before testInt2 is " + t2.getTime());
System.out.println("testInt Objectid is " + t1.uniqueObjId);
System.out.println("testInt2 Objectid is " + t2.uniqueObjId);
swap(t1, t2);
System.out.println("testInt is " + t1.getTime());
System.out.println("testInt2 is " + t2.getTime());
}
public static void swap(Time x, Time y){
Time temp = new Time(300);
System.out.println("Before x is " + x.uniqueObjId);
System.out.println("Before y is " + y.uniqueObjId);
System.out.println("Before temp is " + temp.uniqueObjId);
x = x.getObj();
y = y.getObj();
temp = x;
x = y;
y = temp;
System.out.println("After x objectId is " + x.uniqueObjId);
System.out.println("After y objectId is " + y.uniqueObjId);
System.out.println("After temp objectId is " + temp.uniqueObjId);
}
public Time getObj(){
return this;
}
}
Here are the results:
Before testInt is 100
Before testInt2 is 200
testInt Objectid is 0
testInt2 Objectid is 1
Before x is 0
Before y is 1
Before temp is 2
After x objectId is 1
After y objectId is 0
After temp objectId is 0
testInt is 100
testInt2 is 200
According to the results, x and y point to the actual objects t1 and t2 declared in the main(), however, assignment of t1 to temp and t2 to t1 and finally temp to t2 does not copy their members, mainly the currentTime variable. So I am assuming a way to get actual assignment where all members of an object are copied outside the scope of the object is to overload the default assignment operator? Please let me know if overloading the assignment operator will do the actual assignment instead of just pointing the current variable to the other variable's referenced object.
You need to return those values of x and y and assign to t1 and t2.
In main() :-
List<Time> list = swap(t1,t2);
t1 = list.get(0); t2 = list.get(1);
And change swap() as follows:
public static List<Time> swap(Time x, Time y){
Time temp = new Time(300);
System.out.println("Before x is " + x.uniqueObjId);
System.out.println("Before y is " + y.uniqueObjId);
System.out.println("Before temp is " + temp.uniqueObjId);
x = x.getObj();
y = y.getObj();
temp = x;
x = y;
y = temp;
List<Time> list = new ArrayList<Time>();
list.add(x);
list.add(y);
System.out.println("After x objectId is " + x.uniqueObjId);
System.out.println("After y objectId is " + y.uniqueObjId);
System.out.println("After temp objectId is " + temp.uniqueObjId);
return(list);
}
( I'm beginner )
double x = 0.5;
double y = 0.3;
String[]normal = {"x","y","cos","sin","avg"};
String[]complex = {"cos","sin","avg"};
char coordinate = (char) (new Random().nextInt(2) + 'x');
String result = "";
if(levels == 1){
String value1 = (normal[new Random().nextInt(normal.length)]);
if (value1.equals("sin") ||value1.equals("cos")){
result = value1 + "( pi *" + coordinate + ")";
}
else if(value1.equals("avg")){
result = value1 + "(" + coordinate + "," + coordinate + ")" ;
}
else{
result = value1 ;
}
}else{
String value = (complex[new Random().nextInt(complex.length)]);
if((value.equals("sin") ||value.equals("cos"))&&levels!=0 ){
result = value + "( pi *" + createFunction(levels - 1) + ")";
}
else if(value.equals("avg")&& levels !=0){
result = value +"(" + createFunction (levels - (levels-1)) + "," + createFunction (levels - (levels-1)) + ")" ;
}
else if(value.equals("avg")&& levels ==2){
result = value + "(" + createFunction (levels - 1) + "," + coordinate + ")" ;
}
else{
result = value ;
}
}
return result;
}
double functions = ....................... ;
result will be "sin(pi*cos(pi*x*y))" in String
how to calculate this string and keep in double functions
You are asking how to parse a string containing an arbitrary expression and then evaluate it to get a floating-point result.
That is quite difficult, requiring an expression parser, to convert the string into an expression tree, and an expression tree evaluator, to actually calculate the result.
You can do this using Groovy scripts. The trick is to evaluate your input as a Java-like expression:
public final class Test{
private static GroovyShell createMathShell() {
GroovyShell shell = new GroovyShell();
shell.evaluate("" +
"cos = {double x -> Math.cos(x)}\n" + // predefine functions as lambda
"sin = {double x -> Math.sin(x)}\n" + // expressions
"pi = Math.PI\n" // define pi
);
return shell;
}
public static void main(String[] args) {
GroovyShell shell = createMathShell();
// set values
shell.setVariable("x", 0);
shell.setVariable("y", 1);
// evaluate
double result = (Double) shell.evaluate("sin(pi*cos(pi*x*y))");
System.out.println(result);
}
}
Executing this code will print:
1.2246467991473532E-16
It would be wise to initialise a double and directly write the value into that variable.
Double answer = ....;
When you need the original value, just use the variable answer. When you need it as a string, just use:
String answer_string = String.valueOf(answer);
Or, for example:
System.out.println(String.valueOf(answer));
Math.sin and Math.cos methods will accept double values, and return a double. Simply write a method taking as arguments x and y to return the formula:
double myAlgorithm( double x, double y){
return Math.sin(Math.PI*Math.cos(Math.PI*x*y))
}
This will work passing x and y as int as it will be casted implicitly to double
double myAlgorithm( int x, int y){
return Math.sin(Math.PI*Math.cos(Math.PI*x*y))
}
And, if you want to pass Strings instead of types:
double myAlgorithm( String x, String y){
return Math.sin(Math.PI*Math.cos(Math.PI*(Double.parseDouble(x).doubleValue())*(Double.parseDouble(y).doubleValue())))
}
This should do it:
Double.valueOf(string);