I try to create a Class in Processing,
it includes 3 bool´s, and I want to make a getter, setter, resp. a method which changes the boolean to the other value.
That´s it.
My Code is following:
public class Color_high_low {
private boolean r_higher = true;
private boolean g_higher = true;
private boolean b_higher = true;
Color_high_low() {
r_higher = true;
g_higher = true;
b_higher = true;
}
//Getter
{
boolean get_r_h() {
return r_higher;
}
boolean get_g_h() {
return this.r_higher;
}
boolean get_b_h() {
return this.r_higher;
}
}
//Changer
{
void change_r_h() {
if (r_higher == true) {
r_higher = false;
} else {
r_higher = true;
}
return;
}
void change_g_h() {
if (g_higher == true) {
g_higher = false;
} else {
g_higher = true;
}
return;
}
void change_b_h() {
if (b_higher == true) {
b_higher = false;
} else {
b_higher = true;
}
return;
}
}
//Setter
{
void set_r_h(boolean be_or_not_to_be) {
r_higher = be_or_not_to_be;
return;
}
void set_g_h(boolean be_or_not_to_be) {
g_higher = be_or_not_to_be;
return;
}
void set_b_h(boolean be_or_not_to_be) {
b_higher = be_or_not_to_be;
return;
}
}
}
At the moment I get compile errors by the Return-Types of my methods, but I don´t know why. Do you have ideas?
Answers would be a pleasure!
Compile errors at the moment:
unexpected token: boolean
unexpected token: void
Don´t put methods in extra backets {} for grouping!
I am trying to implement an IncrementalScoreCalculator for the current Kaggle TSP challenge. So, I have been looking at the docs and I have succesfully implemented an EasyScoreCalacultor that returns a HardSoftScore where the hardscore is the number of locations for which every 10th step is not a prime.
what I have looks as follows
#Override
public void beforeVariableChanged(Object o, String s) {
if (o instanceof Domicile) {
return;
}
switch (s) {
case "previousStandstill":
retract((Visit) o);
break;
case "position":
retractPosition((Visit) o);
break;
default:
throw new IllegalArgumentException("Unrecognized variable change " + s);
}
}
#Override
public void afterVariableChanged(Object o, String s) {
if (o instanceof Domicile) {
return;
}
switch (s) {
case "previousStandstill":
insert((Visit) o);
break;
case "position":
insertPosition((Visit) o);
break;
default:
throw new IllegalArgumentException("Unrecognized variable change " + s);
}
where position is a shadow variable.
retractPosition and insertPosition look as follows:
private void retractPosition(Visit visit) {
Integer position = visit.getPosition();
if (position != null) {
if (visit.getLocation().getId() % 10 == 0) {
if (isPrime(position)) {
hardscore--;
}
}
}
}
private void insertPosition(Visit visit) {
Integer position = visit.getPosition();
if (position!= null) {
if (visit.getLocation().getId() % 10 == 0) {
if (isPrime(position)) {
hardscore++;
}
}
}
}
But this somehow does not seem to work correctly and I cannot seem to wrap my head around it. Any help is deeply appreciated.
I am reading this page about coroutines in Python and this Wikipedia page. I saw that there are a few libraries in Java implementing coroutines.
My question is: is there any known reason why the Java designers decided not to implement coroutines so far and is there any plan to include it in a future version of Java?
Thanks.
Actually the concept of a co-routine was the first design of the Java threading system. The wait/notify mechanism is a simplistic form of co-routine where notify is equivalent to yield etc.
Since then much has been done, particularly to make structures thread-safe rather than algorithms. This derives from the realization that it is not the code that must synchronize/yield but the data structure used to communicate between the threads that must be thread-safe.
Project Loom
Continuations and Coroutines will come to Java in the nearer future and they’ll be called virtual threads (also referred to as fibers). There’s a project called Loom:
Project Loom is intended to explore, incubate and deliver Java VM features and APIs built on top of them for the purpose of supporting easy-to-use, high-throughput lightweight concurrency and new programming models on the Java platform. This is accomplished by the addition of the following constructs:
Virtual threads
Delimited continuations
Tail-call elimination
Further reading: https://cr.openjdk.java.net/~rpressler/loom/Loom-Proposal.html
To quote that document:
It is the goal of this project to add a public delimited continuation (or coroutine) construct to the Java platform. However, this goal is secondary to fibers …
Preliminary builds of Project Loom are available now, based on early-access Java 16.
On the "are there any plans ..." part of the question, the answer is:
Not at this stage
The JEP list (http://openjdk.java.net/jeps/0) does not make any mention of coroutines. The list covers features added in Java 8, added or targeted for Java 9, or proposed for future releases.
Interestingly, there was an RFE submitted in March 2013 (https://bugs.openjdk.java.net/browse/JDK-8029988). The RFE only got one vote, and it was closed 9 months with the suggestion to submit a JEP. Nobody has bothered to take the idea any further, which to me is telling.
It's synced with Java 15 build 7.
Link
There's an another choice is here for Java6+
A pythonic coroutine implementation:
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
class CorRunRAII {
private final List<WeakReference<? extends CorRun>> resources = new ArrayList<>();
public CorRunRAII add(CorRun resource) {
if (resource == null) {
return this;
}
resources.add(new WeakReference<>(resource));
return this;
}
public CorRunRAII addAll(List<? extends CorRun> arrayList) {
if (arrayList == null) {
return this;
}
for (CorRun corRun : arrayList) {
add(corRun);
}
return this;
}
#Override
protected void finalize() throws Throwable {
super.finalize();
for (WeakReference<? extends CorRun> corRunWeakReference : resources) {
CorRun corRun = corRunWeakReference.get();
if (corRun != null) {
corRun.stop();
}
}
}
}
class CorRunYieldReturn<ReceiveType, YieldReturnType> {
public final AtomicReference<ReceiveType> receiveValue;
public final LinkedBlockingDeque<AtomicReference<YieldReturnType>> yieldReturnValue;
CorRunYieldReturn(AtomicReference<ReceiveType> receiveValue, LinkedBlockingDeque<AtomicReference<YieldReturnType>> yieldReturnValue) {
this.receiveValue = receiveValue;
this.yieldReturnValue = yieldReturnValue;
}
}
interface CorRun<ReceiveType, YieldReturnType> extends Runnable, Callable<YieldReturnType> {
boolean start();
void stop();
void stop(final Throwable throwable);
boolean isStarted();
boolean isEnded();
Throwable getError();
ReceiveType getReceiveValue();
void setResultForOuter(YieldReturnType resultForOuter);
YieldReturnType getResultForOuter();
YieldReturnType receive(ReceiveType value);
ReceiveType yield();
ReceiveType yield(YieldReturnType value);
<TargetReceiveType, TargetYieldReturnType> TargetYieldReturnType yieldFrom(final CorRun<TargetReceiveType, TargetYieldReturnType> another);
<TargetReceiveType, TargetYieldReturnType> TargetYieldReturnType yieldFrom(final CorRun<TargetReceiveType, TargetYieldReturnType> another, final TargetReceiveType value);
}
abstract class CorRunSync<ReceiveType, YieldReturnType> implements CorRun<ReceiveType, YieldReturnType> {
private ReceiveType receiveValue;
public final List<WeakReference<CorRun>> potentialChildrenCoroutineList = new ArrayList<>();
// Outside
private AtomicBoolean isStarted = new AtomicBoolean(false);
private AtomicBoolean isEnded = new AtomicBoolean(false);
private Throwable error;
private YieldReturnType resultForOuter;
#Override
public boolean start() {
boolean isStarted = this.isStarted.getAndSet(true);
if ((! isStarted)
&& (! isEnded())) {
receive(null);
}
return isStarted;
}
#Override
public void stop() {
stop(null);
}
#Override
public void stop(Throwable throwable) {
isEnded.set(true);
if (throwable != null) {
error = throwable;
}
for (WeakReference<CorRun> weakReference : potentialChildrenCoroutineList) {
CorRun child = weakReference.get();
if (child != null) {
child.stop();
}
}
}
#Override
public boolean isStarted() {
return isStarted.get();
}
#Override
public boolean isEnded() {
return isEnded.get();
}
#Override
public Throwable getError() {
return error;
}
#Override
public ReceiveType getReceiveValue() {
return receiveValue;
}
#Override
public void setResultForOuter(YieldReturnType resultForOuter) {
this.resultForOuter = resultForOuter;
}
#Override
public YieldReturnType getResultForOuter() {
return resultForOuter;
}
#Override
public synchronized YieldReturnType receive(ReceiveType value) {
receiveValue = value;
run();
return getResultForOuter();
}
#Override
public ReceiveType yield() {
return yield(null);
}
#Override
public ReceiveType yield(YieldReturnType value) {
resultForOuter = value;
return receiveValue;
}
#Override
public <TargetReceiveType, TargetYieldReturnType> TargetYieldReturnType yieldFrom(CorRun<TargetReceiveType, TargetYieldReturnType> another) {
return yieldFrom(another, null);
}
#Override
public <TargetReceiveType, TargetYieldReturnType> TargetYieldReturnType yieldFrom(CorRun<TargetReceiveType, TargetYieldReturnType> another, TargetReceiveType value) {
if (another == null || another.isEnded()) {
throw new RuntimeException("Call null or isEnded coroutine");
}
potentialChildrenCoroutineList.add(new WeakReference<CorRun>(another));
synchronized (another) {
boolean isStarted = another.start();
boolean isJustStarting = ! isStarted;
if (isJustStarting && another instanceof CorRunSync) {
return another.getResultForOuter();
}
return another.receive(value);
}
}
#Override
public void run() {
try {
this.call();
}
catch (Exception e) {
e.printStackTrace();
stop(e);
return;
}
}
}
abstract class CorRunThread<ReceiveType, YieldReturnType> implements CorRun<ReceiveType, YieldReturnType> {
private final ExecutorService childExecutorService = newExecutorService();
private ExecutorService executingOnExecutorService;
private static final CorRunYieldReturn DUMMY_COR_RUN_YIELD_RETURN = new CorRunYieldReturn(new AtomicReference<>(null), new LinkedBlockingDeque<AtomicReference>());
private final CorRun<ReceiveType, YieldReturnType> self;
public final List<WeakReference<CorRun>> potentialChildrenCoroutineList;
private CorRunYieldReturn<ReceiveType, YieldReturnType> lastCorRunYieldReturn;
private final LinkedBlockingDeque<CorRunYieldReturn<ReceiveType, YieldReturnType>> receiveQueue;
// Outside
private AtomicBoolean isStarted = new AtomicBoolean(false);
private AtomicBoolean isEnded = new AtomicBoolean(false);
private Future<YieldReturnType> future;
private Throwable error;
private final AtomicReference<YieldReturnType> resultForOuter = new AtomicReference<>();
CorRunThread() {
executingOnExecutorService = childExecutorService;
receiveQueue = new LinkedBlockingDeque<>();
potentialChildrenCoroutineList = new ArrayList<>();
self = this;
}
#Override
public void run() {
try {
self.call();
}
catch (Exception e) {
stop(e);
return;
}
stop();
}
#Override
public abstract YieldReturnType call();
#Override
public boolean start() {
return start(childExecutorService);
}
protected boolean start(ExecutorService executorService) {
boolean isStarted = this.isStarted.getAndSet(true);
if (!isStarted) {
executingOnExecutorService = executorService;
future = (Future<YieldReturnType>) executingOnExecutorService.submit((Runnable) self);
}
return isStarted;
}
#Override
public void stop() {
stop(null);
}
#Override
public void stop(final Throwable throwable) {
if (throwable != null) {
error = throwable;
}
isEnded.set(true);
returnYieldValue(null);
// Do this for making sure the coroutine has checked isEnd() after getting a dummy value
receiveQueue.offer(DUMMY_COR_RUN_YIELD_RETURN);
for (WeakReference<CorRun> weakReference : potentialChildrenCoroutineList) {
CorRun child = weakReference.get();
if (child != null) {
if (child instanceof CorRunThread) {
((CorRunThread)child).tryStop(childExecutorService);
}
}
}
childExecutorService.shutdownNow();
}
protected void tryStop(ExecutorService executorService) {
if (this.executingOnExecutorService == executorService) {
stop();
}
}
#Override
public boolean isEnded() {
return isEnded.get() || (
future != null && (future.isCancelled() || future.isDone())
);
}
#Override
public boolean isStarted() {
return isStarted.get();
}
public Future<YieldReturnType> getFuture() {
return future;
}
#Override
public Throwable getError() {
return error;
}
#Override
public void setResultForOuter(YieldReturnType resultForOuter) {
this.resultForOuter.set(resultForOuter);
}
#Override
public YieldReturnType getResultForOuter() {
return this.resultForOuter.get();
}
#Override
public YieldReturnType receive(ReceiveType value) {
LinkedBlockingDeque<AtomicReference<YieldReturnType>> yieldReturnValue = new LinkedBlockingDeque<>();
offerReceiveValue(value, yieldReturnValue);
try {
AtomicReference<YieldReturnType> takeValue = yieldReturnValue.take();
return takeValue == null ? null : takeValue.get();
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
#Override
public ReceiveType yield() {
return yield(null);
}
#Override
public ReceiveType yield(final YieldReturnType value) {
returnYieldValue(value);
return getReceiveValue();
}
#Override
public <TargetReceiveType, TargetYieldReturnType> TargetYieldReturnType yieldFrom(final CorRun<TargetReceiveType, TargetYieldReturnType> another) {
return yieldFrom(another, null);
}
#Override
public <TargetReceiveType, TargetYieldReturnType> TargetYieldReturnType yieldFrom(final CorRun<TargetReceiveType, TargetYieldReturnType> another, final TargetReceiveType value) {
if (another == null || another.isEnded()) {
throw new RuntimeException("Call null or isEnded coroutine");
}
boolean isStarted = false;
potentialChildrenCoroutineList.add(new WeakReference<CorRun>(another));
synchronized (another) {
if (another instanceof CorRunThread) {
isStarted = ((CorRunThread)another).start(childExecutorService);
}
else {
isStarted = another.start();
}
boolean isJustStarting = ! isStarted;
if (isJustStarting && another instanceof CorRunSync) {
return another.getResultForOuter();
}
TargetYieldReturnType send = another.receive(value);
return send;
}
}
#Override
public ReceiveType getReceiveValue() {
setLastCorRunYieldReturn(takeLastCorRunYieldReturn());
return lastCorRunYieldReturn.receiveValue.get();
}
protected void returnYieldValue(final YieldReturnType value) {
CorRunYieldReturn<ReceiveType, YieldReturnType> corRunYieldReturn = lastCorRunYieldReturn;
if (corRunYieldReturn != null) {
corRunYieldReturn.yieldReturnValue.offer(new AtomicReference<>(value));
}
}
protected void offerReceiveValue(final ReceiveType value, LinkedBlockingDeque<AtomicReference<YieldReturnType>> yieldReturnValue) {
receiveQueue.offer(new CorRunYieldReturn(new AtomicReference<>(value), yieldReturnValue));
}
protected CorRunYieldReturn<ReceiveType, YieldReturnType> takeLastCorRunYieldReturn() {
try {
return receiveQueue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
protected void setLastCorRunYieldReturn(CorRunYieldReturn<ReceiveType,YieldReturnType> lastCorRunYieldReturn) {
this.lastCorRunYieldReturn = lastCorRunYieldReturn;
}
protected ExecutorService newExecutorService() {
return Executors.newCachedThreadPool(getThreadFactory());
}
protected ThreadFactory getThreadFactory() {
return new ThreadFactory() {
#Override
public Thread newThread(final Runnable runnable) {
Thread thread = new Thread(runnable);
thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, Throwable throwable) {
throwable.printStackTrace();
if (runnable instanceof CorRun) {
CorRun self = (CorRun) runnable;
self.stop(throwable);
thread.interrupt();
}
}
});
return thread;
}
};
}
}
Now you can use pythonic coroutines in this way
(e.g. fibonacci numbers)
Thread Version:
class Fib extends CorRunThread<Integer, Integer> {
#Override
public Integer call() {
Integer times = getReceiveValue();
do {
int a = 1, b = 1;
for (int i = 0; times != null && i < times; i++) {
int temp = a + b;
a = b;
b = temp;
}
// A pythonic "yield", i.e., it returns `a` to the caller and waits `times` value from the next caller
times = yield(a);
} while (! isEnded());
setResultForOuter(Integer.MAX_VALUE);
return getResultForOuter();
}
}
class MainRun extends CorRunThread<String, String> {
#Override
public String call() {
// The fib coroutine would be recycled by its parent
// (no requirement to call its start() and stop() manually)
// Otherwise, if you want to share its instance and start/stop it manually,
// please start it before being called by yieldFrom() and stop it in the end.
Fib fib = new Fib();
String result = "";
Integer current;
int times = 10;
for (int i = 0; i < times; i++) {
// A pythonic "yield from", i.e., it calls fib with `i` parameter and waits for returned value as `current`
current = yieldFrom(fib, i);
if (fib.getError() != null) {
throw new RuntimeException(fib.getError());
}
if (current == null) {
continue;
}
if (i > 0) {
result += ",";
}
result += current;
}
setResultForOuter(result);
return result;
}
}
Sync(non-thread) version:
class Fib extends CorRunSync<Integer, Integer> {
#Override
public Integer call() {
Integer times = getReceiveValue();
int a = 1, b = 1;
for (int i = 0; times != null && i < times; i++) {
int temp = a + b;
a = b;
b = temp;
}
yield(a);
return getResultForOuter();
}
}
class MainRun extends CorRunSync<String, String> {
#Override
public String call() {
CorRun<Integer, Integer> fib = null;
try {
fib = new Fib();
} catch (Exception e) {
e.printStackTrace();
}
String result = "";
Integer current;
int times = 10;
for (int i = 0; i < times; i++) {
current = yieldFrom(fib, i);
if (fib.getError() != null) {
throw new RuntimeException(fib.getError());
}
if (current == null) {
continue;
}
if (i > 0) {
result += ",";
}
result += current;
}
stop();
setResultForOuter(result);
if (Utils.isEmpty(result)) {
throw new RuntimeException("Error");
}
return result;
}
}
Execution(Both versions will work):
// Run the entry coroutine
MainRun mainRun = new MainRun();
mainRun.start();
// Wait for mainRun ending for 5 seconds
long startTimestamp = System.currentTimeMillis();
while(!mainRun.isEnded()) {
if (System.currentTimeMillis() - startTimestamp > TimeUnit.SECONDS.toMillis(5)) {
throw new RuntimeException("Wait too much time");
}
}
// The result should be "1,1,2,3,5,8,13,21,34,55"
System.out.println(mainRun.getResultForOuter());
I have defined a filter for the termination condition by k-means.
if I run my app it always compute only one iteration.
I think the problem is here:
DataSet<GeoTimeDataCenter> finalCentroids = loop.closeWith(newCentroids, newCentroids.join(loop).where("*").equalTo("*").filter(new MyFilter()));
or maybe the filter function:
public static final class MyFilter implements FilterFunction<Tuple2<GeoTimeDataCenter, GeoTimeDataCenter>> {
private static final long serialVersionUID = 5868635346889117617L;
public boolean filter(Tuple2<GeoTimeDataCenter, GeoTimeDataCenter> tuple) throws Exception {
if(tuple.f0.equals(tuple.f1)) {
return true;
}
else {
return false;
}
}
}
best regards,
paul
my full code here:
public void run() {
//load properties
Properties pro = new Properties();
FileSystem fs = null;
try {
pro.load(FlinkMain.class.getResourceAsStream("/config.properties"));
fs = FileSystem.get(new URI(pro.getProperty("hdfs.namenode")),new org.apache.hadoop.conf.Configuration());
} catch (Exception e) {
e.printStackTrace();
}
int maxIteration = Integer.parseInt(pro.getProperty("maxiterations"));
String outputPath = fs.getHomeDirectory()+pro.getProperty("flink.output");
// set up execution environment
ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
// get input points
DataSet<GeoTimeDataTupel> points = getPointDataSet(env);
DataSet<GeoTimeDataCenter> centroids = null;
try {
centroids = getCentroidDataSet(env);
} catch (Exception e1) {
e1.printStackTrace();
}
// set number of bulk iterations for KMeans algorithm
IterativeDataSet<GeoTimeDataCenter> loop = centroids.iterate(maxIteration);
DataSet<GeoTimeDataCenter> newCentroids = points
// compute closest centroid for each point
.map(new SelectNearestCenter(this.getBenchmarkCounter())).withBroadcastSet(loop, "centroids")
// count and sum point coordinates for each centroid
.groupBy(0).reduceGroup(new CentroidAccumulator())
// compute new centroids from point counts and coordinate sums
.map(new CentroidAverager(this.getBenchmarkCounter()));
// feed new centroids back into next iteration with termination condition
DataSet<GeoTimeDataCenter> finalCentroids = loop.closeWith(newCentroids, newCentroids.join(loop).where("*").equalTo("*").filter(new MyFilter()));
DataSet<Tuple2<Integer, GeoTimeDataTupel>> clusteredPoints = points
// assign points to final clusters
.map(new SelectNearestCenter(-1)).withBroadcastSet(finalCentroids, "centroids");
// emit result
clusteredPoints.writeAsCsv(outputPath+"/points", "\n", " ");
finalCentroids.writeAsText(outputPath+"/centers");//print();
// execute program
try {
env.execute("KMeans Flink");
} catch (Exception e) {
e.printStackTrace();
}
}
public static final class MyFilter implements FilterFunction<Tuple2<GeoTimeDataCenter, GeoTimeDataCenter>> {
private static final long serialVersionUID = 5868635346889117617L;
public boolean filter(Tuple2<GeoTimeDataCenter, GeoTimeDataCenter> tuple) throws Exception {
if(tuple.f0.equals(tuple.f1)) {
return true;
}
else {
return false;
}
}
}
I think the problem is the filter function (modulo the code you haven't posted). Flink's termination criterion works the following way: The termination criterion is met if the provided termination DataSet is empty. Otherwise the next iteration is started if the maximum number of iterations has not been exceeded.
Flink's filter function keeps only those elements for which the FilterFunction returns true. Thus, with your MyFilter implementation you only keep the centroids which are before and after the iteration identical. This implies that you'll obtain an empty DataSet if all centroids have changed and, thus, the iteration terminates. This is clearly the inverse of the actual termination criterion. The termination criterion should be: Continue with k-means as long as there is a centroid which has changed.
You can do this with a coGroup function where you emit elements if there is no matching centroid from the preceding centroid DataSet. This is similar to a left outer join, just that you discard non null matches.
public static void main(String[] args) throws Exception {
// set up the execution environment
final ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
DataSet<Element> oldDS = env.fromElements(new Element(1, "test"), new Element(2, "test"), new Element(3, "foobar"));
DataSet<Element> newDS = env.fromElements(new Element(1, "test"), new Element(3, "foobar"), new Element(4, "test"));
DataSet<Element> filtered = newDS.coGroup(oldDS).where("*").equalTo("*").with(new FilterCoGroup());
filtered.print();
}
public static class FilterCoGroup implements CoGroupFunction<Element, Element, Element> {
#Override
public void coGroup(
Iterable<Element> newElements,
Iterable<Element> oldElements,
Collector<Element> collector) throws Exception {
List<Element> persistedElements = new ArrayList<Element>();
for(Element element: oldElements) {
persistedElements.add(element);
}
for(Element newElement: newElements) {
boolean contained = false;
for(Element oldElement: persistedElements) {
if(newElement.equals(oldElement)){
contained = true;
}
}
if(!contained) {
collector.collect(newElement);
}
}
}
}
public static class Element implements Key {
private int id;
private String name;
public Element(int id, String name) {
this.id = id;
this.name = name;
}
public Element() {
this(-1, "");
}
#Override
public int hashCode() {
return 31 + 7 * name.hashCode() + 11 * id;
}
#Override
public boolean equals(Object obj) {
if(obj instanceof Element) {
Element element = (Element) obj;
return id == element.id && name.equals(element.name);
} else {
return false;
}
}
#Override
public int compareTo(Object o) {
if(o instanceof Element) {
Element element = (Element) o;
if(id == element.id) {
return name.compareTo(element.name);
} else {
return id - element.id;
}
} else {
throw new RuntimeException("Comparing incompatible types.");
}
}
#Override
public void write(DataOutputView dataOutputView) throws IOException {
dataOutputView.writeInt(id);
dataOutputView.writeUTF(name);
}
#Override
public void read(DataInputView dataInputView) throws IOException {
id = dataInputView.readInt();
name = dataInputView.readUTF();
}
#Override
public String toString() {
return "(" + id + "; " + name + ")";
}
}
I have implemented the algorithm that I have found on this link to evaluate an arithmetic expression for j2me. But it works fine only when I have single digit operands i.e. 2, 5, 7, 3 but not for 456, 56, 34.45 etc. I did some changes as i knew i had to add the numbers found not one by one but till we end with a digit. Then I found this link also but still things didn't go well as expected. First I had tried the exp4j library but I guess that does not work on j2me. The code has become very messy right now. Could I get any opinions on how should I go about this problem? Any help on this would be appreciated.
Code that initially worked only for single digit operands:
import java.util.Stack;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
public class SampleInfixToPostfixToResult {
static Stack stack=new Stack();
static StringBuffer p=new StringBuffer();
static Vector v=new Vector();
public static StringBuffer toPostfix(String q)
{
for(int i=0;i<q.length();i++)
{
if(q.charAt(i)=='0'||q.charAt(i)=='1'||q.charAt(i)=='2'||q.charAt(i)=='3'||q.charAt(i)=='4'||q.charAt(i)=='5'||q.charAt(i)=='6'||q.charAt(i)=='7'||q.charAt(i)=='8'||q.charAt(i)=='9')
{
p.append(q.charAt(i));
}
else if(q.charAt(i)=='(')
{
stack.push(q.charAt(i));
}
else if(q.charAt(i)==')')
{
for(int j=0;!stack.empty()&&!stack.peek().equals('(');j++)
{
p.append(stack.pop());
}
stack.pop();
}
else if(q.charAt(i)=='+'||q.charAt(i)=='-'||q.charAt(i)=='/'||q.charAt(i)=='*')
{
if(stack.empty()||stack.peek().equals('('))
stack.push(q.charAt(i));
else
{
while(!stack.empty()&&!stack.peek().equals('(')&&isHigh(q.charAt(i), stack.peek()))
{
p.append(stack.pop());
}
stack.push(q.charAt(i));
}
}
}
while(!stack.empty())
{
p.append(stack.pop());
}
System.out.println(p);
return p;
}
public static boolean isHigh(char op, Object AtStack)
{
char opAtStack=AtStack.toString().charAt(0);
boolean isHigh=false;
if((op==opAtStack))
isHigh=true;
if((op=='+'||op=='-')&&(opAtStack=='/'||opAtStack=='*'))
{
isHigh=true;
}
if((op=='+'&&opAtStack=='-')||(op=='-'&&opAtStack=='+')||(op=='/'&&opAtStack=='*')||(op=='*'&&opAtStack=='/'))
{
isHigh=true;
}
return isHigh;
}
public static double result(StringBuffer p)
{
for(int i=0;i<p.length();i++)
{
System.out.println(p.charAt(i));
if(p.charAt(i)=='0'||p.charAt(i)=='1'||p.charAt(i)=='2'||p.charAt(i)=='3'||p.charAt(i)=='4'||p.charAt(i)=='5'||p.charAt(i)=='6'||p.charAt(i)=='7'||p.charAt(i)=='8'||p.charAt(i)=='9')
{
stack.push(p.charAt(i));
}
if(p.charAt(i)=='+'||p.charAt(i)=='-'||p.charAt(i)=='/'||p.charAt(i)=='*')
{
double a=Double.parseDouble(stack.pop().toString());
double b=Double.parseDouble(stack.pop().toString());
if(p.charAt(i)=='+')
{
stack.push(b+a);
}
else if(p.charAt(i)=='-')
{
stack.push(b-a);
}
else if(p.charAt(i)=='/')
{
stack.push(b/a);
}
else if(p.charAt(i)=='*')
{
stack.push(b*a);
}
}
}
System.out.println(stack);
return 0;
}
public static void main(String[] args) {
// TODO code application logic here
String s=new String("65*(76+2)-0/4+(2*5-6*(2*5))");
SampleInfixToPostfixToResult.result(SampleInfixToPostfixToResult.toPostfix(s));
System.out.println(66*(76+2)-0/4+(2*5-6*(2*5)));
}
}
Updated code that I worked on for evaluation of multi-digit operand (really messed up)
import java.util.Stack;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
public class SampleInfixToPostfixToResult {
static Stack stack=new Stack();
static StringBuffer p=new StringBuffer();
static Vector v=new Vector();
public static Vector toPostfix(String q)
{
for(int i=0;i<q.length();i++)
{
if(q.charAt(i)=='0'||q.charAt(i)=='1'||q.charAt(i)=='2'||q.charAt(i)=='3'||q.charAt(i)=='4'||q.charAt(i)=='5'||q.charAt(i)=='6'||q.charAt(i)=='7'||q.charAt(i)=='8'||q.charAt(i)=='9')
{
StringBuffer tn=new StringBuffer();
while(i<q.length()&&(q.charAt(i)=='0'||q.charAt(i)=='1'||q.charAt(i)=='2'||q.charAt(i)=='3'||q.charAt(i)=='4'||q.charAt(i)=='5'||q.charAt(i)=='6'||q.charAt(i)=='7'||q.charAt(i)=='8'||q.charAt(i)=='9'))
{
tn.append(q.charAt(i++));
}
v.add(tn);
}
else if(q.charAt(i)=='(')
{
stack.push(q.charAt(i));
}
else if(q.charAt(i)==')')
{
for(int j=0;!stack.empty()&&!stack.peek().equals('(');j++)
{
v.add(stack.pop());
}
stack.pop();
}
else if(q.charAt(i)=='+'||q.charAt(i)=='-'||q.charAt(i)=='/'||q.charAt(i)=='*')
{
if(stack.empty()||stack.peek().equals('('))
stack.push(q.charAt(i));
else
{
while(!stack.empty()&&!stack.peek().equals('(')&&isHigh(q.charAt(i), stack.peek()))
{
v.add(stack.pop());
}
stack.push(q.charAt(i));
}
}
}
while(!stack.empty())
{
v.add(stack.pop());
}
return v;
}
public static boolean isHigh(char op, Object AtStack)
{
char opAtStack=AtStack.toString().charAt(0);
boolean isHigh=false;
if((op==opAtStack))
isHigh=true;
if((op=='+'||op=='-')&&(opAtStack=='/'||opAtStack=='*'))
{
isHigh=true;
}
if((op=='+'&&opAtStack=='-')||(op=='-'&&opAtStack=='+')||(op=='/'&&opAtStack=='*')||(op=='*'&&opAtStack=='/'))
{
isHigh=true;
}
return isHigh;
}
public static double result(Vector p)
{
for(int i=0;i<p.size();i++)
{
System.out.println(p.get(i));
if(p.get(i)=="0"||p.get(i)=="1"||p.get(i)=="2"||p.get(i)=="3"||p.get(i)=="4"||p.get(i)=="5"||p.get(i)=="6"||p.get(i)=="7"||p.get(i)=="8"||p.get(i)=="9")
{
StringBuffer tn=new StringBuffer();
while(i<p.size()&&(p.get(i)=="0"||p.get(i)=="1"||p.get(i)=="2"||p.get(i)=="3"||p.get(i)=="4"||p.get(i)=="5"||p.get(i)=="6"||p.get(i)=="7"||p.get(i)=="8"||p.get(i)=="9"))
{
tn.append(p.get(i++));
}
System.out.println("This is the full number :"+tn);
stack.push(tn);
}
if(p.get(i)=="+"||p.get(i)=="-"||p.get(i)=="/"||p.get(i)=="*")
{
double a=Double.parseDouble(stack.pop().toString());
double b=Double.parseDouble(stack.pop().toString());
if(p.get(i)=="+")
{
stack.push(b+a);
}
else if(p.get(i)=="-")
{
stack.push(b-a);
}
else if(p.get(i)=="/")
{
stack.push(b/a);
}
else if(p.get(i)=="*")
{
stack.push(b*a);
}
}
}
System.out.println("Final value: "+stack);
return 0;
}
public static void main(String[] args) {
// TODO code application logic here
String s=new String("65*(79+22)-0/4+(29*5-6*(2*5))");
SampleInfixToPostfixToResult.result(SampleInfixToPostfixToResult.toPostfix(s));
//System.out.println(65*(79+22)-0/4+(29*5-6*(2*5)));
}
}
Solution:
1.Function toPostfix() now returns stack instead of vector, as now the postfix expression is added to the stack eg, [34,57.+] etc.
2.Edited the code for storing all the digits to the stack by traversing the string till we have a number.(see code till line no 29)
import java.util.Stack;
import java.util.Vector;
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* #author Sandeep
*/
public class Main {
static Stack stack=new Stack();
static Stack stackT=new Stack();
//static Vector v=new Vector();
//static StringBuffer p=new StringBuffer();
public static Stack toPostfix(String q)
{
for(int i=0;i<q.length();i++)
{
if(q.charAt(i)=='0'||q.charAt(i)=='1'||q.charAt(i)=='2'||q.charAt(i)=='3'||q.charAt(i)=='4'||q.charAt(i)=='5'||q.charAt(i)=='6'||q.charAt(i)=='7'||q.charAt(i)=='8'||q.charAt(i)=='9')
{
StringBuffer p=new StringBuffer();
while(q.charAt(i)=='0'||q.charAt(i)=='1'||q.charAt(i)=='2'||q.charAt(i)=='3'||q.charAt(i)=='4'||q.charAt(i)=='5'||q.charAt(i)=='6'||q.charAt(i)=='7'||q.charAt(i)=='8'||q.charAt(i)=='9')
p.append(q.charAt(i++));
stackT.push(p);
i--;
}
else if(q.charAt(i)=='(')
{
stack.push(q.charAt(i));
}
else if(q.charAt(i)==')')
{
for(int j=0;!stack.empty()&&!stack.peek().equals('(');j++)
{
stackT.push(stack.pop().toString());
}
stack.pop();
}
else if(q.charAt(i)=='+'||q.charAt(i)=='-'||q.charAt(i)=='/'||q.charAt(i)=='*')
{
if(stack.empty()||stack.peek().equals('('))
stack.push(q.charAt(i));
else
{
while(!stack.empty()&&!stack.peek().equals('(')&&isHigh(q.charAt(i), stack.peek()))
{
stackT.push(stack.pop().toString());
}
stack.push(q.charAt(i));
}
}
}
while(!stack.empty())
{
stackT.push(stack.pop().toString());
}
System.out.println(stackT);
return stackT;
}
//problem lies here
public static boolean isHigh(char op, Object AtStack)
{
char opAtStack=AtStack.toString().charAt(0);
boolean isHigh=false;
if((op==opAtStack))
isHigh=true;
if((op=='+'||op=='-')&&(opAtStack=='/'||opAtStack=='*'))
{
isHigh=true;
}
if((op=='+'&&opAtStack=='-')||(op=='-'&&opAtStack=='+')||(op=='/'&&opAtStack=='*')||(op=='*'&&opAtStack=='/'))
{
isHigh=true;
}
return isHigh;
}
public static double result(Stack p)
{
for(int i=0;i<p.size();i++)
{
if(p.get(i).toString().startsWith("0")||p.get(i).toString().startsWith("1")||p.get(i).toString().startsWith("2")||p.get(i).toString().startsWith("3")||p.get(i).toString().startsWith("4")||p.get(i).toString().startsWith("5")||p.get(i).toString().startsWith("6")||p.get(i).toString().startsWith("7")||p.get(i).toString().startsWith("8")||p.get(i).toString().startsWith("9"))
{
stack.push(p.get(i));
}
if(p.get(i).toString().equals("+")||p.get(i).toString().equals("-")||p.get(i).toString().equals("/")||p.get(i).toString().equals("*"))
{
double a=Double.parseDouble(stack.pop().toString());
double b=Double.parseDouble(stack.pop().toString());
if(p.get(i).equals("+"))
{
stack.push(b+a);
}
else if(p.get(i).equals("-"))
{
stack.push(b-a);
}
else if(p.get(i).equals("/"))
{
stack.push(b/a);
}
else if(p.get(i).equals("*"))
{
stack.push(b*a);
}
}
}
System.out.println(stack);
return 0;
}
public static void main(String[] args) {
// TODO code application logic here
String s=new String("159*(79+23)-10/4+(22*54-67*(25*58))");
Main.result(Main.toPostfix(s));
System.out.println(159*(79+23)-10/4+(22*54-67*(25*58)));
}
}