Passing method in other method Java - java

I want to make a simple program to compare how long time takes rewrite and print out collection of Strings by `for loop`, `foreach` or `stream`. String is sentence where it replaces "i" by "y". In my case I made `count()` where I set to count `stream()` method but I want to make universal measuring method. But i dont know how to do it... It should works like: in Main class is `counter(forLoop);` It should call `forLoop();` from Method class `counter(forEach);` It should call `forEach();` from Metrod class`counter(stream);` It should call ` stream();` From Method class IDont know how to pass method as a parameter
I have class where are those metods:
import java.util.*;
import java.util.stream.*;
public class Methods {
private List<String> sentence = new ArrayList<>();
private String oldLetter = "i";
private String newLetter = "y";
private String methodType;
public String getMethodType() {
return methodType;
}
//making a collection with String
public void setSizeOfCollection(int size){
for (int i = 0; i < size; i++) {
sentence.add("Siti Zbinek plitce zvikal sirovi pelinek.");
}
}
public void forLoop(){
methodType = "For loop";
for (int i = 0; i < sentence.size(); i++) {
for (int j = 0; j < sentence.size(); j++) {
String replaceLetters = sentence.get(j);
replaceLetters = replaceLetters.replaceAll(oldLetter, newLetter);
sentence.set(j, replaceLetters);
}
System.out.println(sentence.get(i));
}
}
public void forEach(){
methodType = "For each";
String replacedLetters = "";
for(String oneLine: sentence){
for(String originalLetters: sentence){
replacedLetters = originalLetters.replaceAll(oldLetter,newLetter);
}
System.out.println(replacedLetters);
}
}
public void stream(){
methodType= "Stream";
sentence.stream()
.map(e->e.replaceAll(oldLetter,newLetter))
.collect(Collectors.toList())
.forEach(System.out::println);
}
}
This is count() that works fine, but only for method stream(). In comment is my imagine how it should be. But I dont know how it do by Java :(
import org.apache.commons.lang.time.*;
public class Counter {
private Methods methods;
private String methodType;
private StopWatch stopWatch = new StopWatch();
long timeTaken = 0;
//here should be something like any method as a parameter XXX xxx
// public void count(Methods methods XXX xxx)
public void count(Methods methods){
stopWatch.start();
// here sould be something what call any function by your choice, not only stream()
// methods.xxx;
methods.stream();
stopWatch.stop();
timeTaken= stopWatch.getTime();
System.out.println(methods.getMethodType()+" takes "+ timeTaken + " ms." );
}
}
And finally Main class
public class Main {
public static void main(String[] args) {
Methods methods = new Methods();
Counter counter = new Counter();
methods.setSizeOfCollection(10000);
counter.count(methods);
//here should be finally three times method, with different parameters:
// counter.count(methods, forEach);
// counter.count(methods, forLoop);
// counter.count(methods, stream);
}
}
Any advice please?

All your methods have the signature void(). Consequently, a reference to each method can be stored in a Runnable instance.
public void count(final Runnable method) {
stopWatch.start();
method.run();
stopWatch.stop();
timeTaken= stopWatch.getTime();
System.out.println(methods.getMethodType()+" takes "+ timeTaken + " ms.");
}
And then call as:
final Methods methods = new Methods();
final Counter counter = new Counter();
methods.setSizeOfCollection(10000);
counter.count(methods::stream); // or count(() -> methods.stream());
counter.count(methods::forEach); // count(() -> methods.forEach());
counter.count(methods::loop); // count(() -> methods.loop());
To be able to use method refs or lambdas, you need to have at least Java 8. For earlier Java versions, you would need to implement Runnable with an anonymous class, e.g.
counter.count(new Runnable() {
#Override public void run() { methods.stream(); }
});
or look up the methods by name via Reflection, but Reflection is usually the slowest option.
PS. Note however that your way of measuring method execution times is flawed; see How do I write a correct micro-benchmark in Java? for directions. This answer only explains the part of passing "methods" to another method.

you could pass the method name as a string and look for it with reflexion.

Related

How to add to array in main?

I have created an array which I wanted to control from main. My code runs, but I don't know how to add integers to the array from the main class. Also as each ConcreteSubject has its own storage array, how would i change this to store them all in the same array?
public class ConcreteSubject extends AbstractSpy
{
private AbstractSpy[] spies = new AbstractSpy[10];
private int i = 0;
public void addSpy(AbstractSpy s) {
if (i < spies.length) {
spies[i] = s;
System.out.println("spy added at index " + i);
i++;
}
}
}
public class TestClass
{
public static void main(String[] args) {
ConcreteSubject cs = new ConcreteSubject();
AbstractSpy spies = new AbstractSpy() {
#Override
public void addSpy(AbstractSpy spies) {
}
};
cs.addSpy(cs);
spies.addSpy(spies);
}
}
It seems like your program logic is a little borked. This bit in particular doesn't make much sense:
***AbstractSpy spies = new AbstractSpy() {
#Override
public void addSpy(AbstractSpy spies) {
}
};
cs.addSpy(cs);
***spies.addSpy(spies);
What you're doing is creating TWO AbstractSpy instances, one named cs and one named spies. On that last line you're adding spies to itself! That doesn't help you at all.
Note that AbstractSpy is the most granular unit in your setup - it shouldn't have an addSpy() method and its own internal array, it should be the thing that's added to something else's array!
Here's the same code, but cleaned up a bit:
public abstract class AbstractSpy { }
public class ConcreteSpy extends AbstractSpy { }
public class ConcreteSubject {
private AbstractSpy[] spies = new AbstractSpy[10];
private int i = 0;
public void addSpy(AbstractSpy spy) {
if (i < spies.length)
{
spies[i] = spy;
System.out.println("spy added at index " + i);
i++;
}
}
}
public class TestClass {
public static void main(String[] args) {
ConcreteSubject cs = new ConcreteSubject();
AbstractSpy spy = new ConcreteSpy();
cs.addSpy(spy);
}
}
The big difference here is that ConcreteSpy is an implementation of AbstractSpy that you can add to your ConcreteSubject's array of spies. I think you might have been confused by Java's insistence that you can't create an instance of an abstract class on its own unless you supply an anonymous class that inherits from the abstract class.

How to call a Method to another Method in the same class

I have a method called countDirectSimilarity, in this method I want to call another method, but I find it difficult to call it, can you help me?
here the source code, i will call method name countAggrIntStrength
private double countDirectSimilarity(double[][] matrixEgoNetwork, int index) {
double sim=0;
for (int i = 0; i < matrixEgoNetwork.length; i++) {
//here the trouble
if (matrixEgoNetwork[i][0]==this.countAggrIntStrength(*here the error*) && matrixEgoNetwork[i][index]!=0) {
sim++;
}
}
return sim;
}
this is method that I want to call
public double countAggrIntStrength(Map<DTNHost, ArrayList<Double>> neighborsHist) {
double AggrIntStrength = 0;
double lambda = 0, sigma = 0;
for (Map.Entry<DTNHost, ArrayList<Double>> data : neighborsHist.entrySet()) {
lambda = data.getValue().get(0);
sigma = data.getValue().get(1);
AggrIntStrength = this.countAgrIntStrength(lambda, sigma);
}
return AggrIntStrength;
}
another problem is that the data structure that I want to enter into
this.countAggrIntStrength()
is in another class, can you help me?
Use static
public static double countAggrIntStrength...
And in your method do not need this.countDirectSimilarity, you can just directly call countDirectSimilarity method.
Get the data structure from the other class using a getter:
otherClassName.getMap()
Then pass it to your method within the first class, either within the method call:
countAggrIntStrength(otherClassName.getMap());
Or by saving it first:
Map<DTNHost, ArrayList<Double>> mapToPass = otherClassName.getMap();
countAggrIntStrength(mapToPass)
You'll need a getter in the other class:
public Map getMap(){
return variableThatStoresTheMap;
}
if you don't already have one.
Some data Structure class which holds neighborsHist map.
public class DataStructure {
Map<DTNHost, ArrayList<Double>> neighborsHist;
public Map<DTNHost, ArrayList<Double>> getNeighborsHist() {
return neighborsHist;
}
public void setNeighborsHist(Map<DTNHost, ArrayList<Double>> neighborsHist) {
this.neighborsHist = neighborsHist;
}
public void businessLogicFunc() {
//business logic function.
...
}
}
Inside your countDirectSimilarity function call get method.
public DataStructure dataStructure;
private double countDirectSimilarity(double[][] matrixEgoNetwork, int index) {
double sim=0;
for (int i = 0; i < matrixEgoNetwork.length; i++) {
if (matrixEgoNetwork[i][0]==this.countAggrIntStrength(dataStructure.getNeighborsHist()) &&
matrixEgoNetwork[i][index]!=0) {
sim++;
}
}
return sim;
}

How to increment an instance with setter?

I have a little problem in a simple class.
import java.util.Random;
public class fileTest {
private static Random rand = new Random();;
private int randOne = rand.nextInt(10);
private String strOne = String.format("%02d", this.randOne);
public int getRandOne() {
return randOne;
}
public void setRandOne(int randOne) {
this.randOne = randOne +1;
}
public String getStrOne() {
return strOne;
}
}
My "launcher"
public class launch {
public static void main(String[] args) {
fileTest fileA = new fileTest();
System.out.println(fileA.getStrOne());
//FunctionDoMyStuff...
fileA.setRandOne(fileA.getRandOne());
System.out.println(fileA.getRandOne());
//RandOne is increment
System.out.println(fileA.getStrOne());
//StrOne is not
}
}
My idea is to create a random number and transform it into a string.
After finishing my stuff, I need to increment my string.
But the result after the setter is the same as in the beginning. I think I don't understand everything about a getter/setter.
Can anyone help me to understand my mistake?
This happens once at the time that your instance is created:
private String strOne = String.format("%02d", this.randOne);
It isn't automatically run again after you change randOne. The solution is to remove the strOne field altogether and construct the String inside the getter:
public String getStrOne() {
return String.format("%02d", this.randOne);
}
You don't need to store a dynamically derived value.
The behaviour of your method setRandOne doesn't match what people might reasonably expect a set method to do. A method that does what yours does could be described as setRandOneToOneHigherThan(int value). Or you could call it incrementRandOne() but then the body needs to do this.randOne = this.randOne + 1; (or this.randOne++;). Or you could make it a normal setter and do the incrementing while you call the method: fileA.setRandOne(fileA.getRandOne() + 1);.

Is it possible to get StackOverflowError without recursion?

I have a task to get "StackOverflowError" in java without using -Xss and recursion. I really don't have ideas... Only some nonsense like generating huge java class at runtime, compile it and invoke...
Java stores primitive types on the stack. Objects created in local scope are allocated on the heap, with the reference to them on the stack.
You can overflow the stack without recursion by allocating too many primitive types in method scope. With normal stack size settings, you would have to allocate an excessive number of variables to overflow.
Here is the implementation of Eric J. idea of generating excessive number of local variables using javassist library:
class SoeNonRecursive {
static final String generatedMethodName = "holderForVariablesMethod";
#SneakyThrows
Class<?> createClassWithLotsOfLocalVars(String generatedClassName, final int numberOfLocalVarsToGenerate) {
ClassPool pool = ClassPool.getDefault();
CtClass generatedClass = pool.makeClass(generatedClassName);
CtMethod generatedMethod = CtNewMethod.make(getMethodBody(numberOfLocalVarsToGenerate), generatedClass);
generatedClass.addMethod(generatedMethod);
return generatedClass.toClass();
}
private String getMethodBody(final int numberOfLocalVarsToGenerate) {
StringBuilder methodBody = new StringBuilder("public static long ")
.append(generatedMethodName).append("() {")
.append(System.lineSeparator());
StringBuilder antiDeadCodeEliminationString = new StringBuilder("long result = i0");
long i = 0;
while (i < numberOfLocalVarsToGenerate) {
methodBody.append(" long i").append(i)
.append(" = ").append(i).append(";")
.append(System.lineSeparator());
antiDeadCodeEliminationString.append("+").append("i").append(i);
i++;
}
antiDeadCodeEliminationString.append(";");
methodBody.append(" ").append(antiDeadCodeEliminationString)
.append(System.lineSeparator())
.append(" return result;")
.append(System.lineSeparator())
.append("}");
return methodBody.toString();
}
}
and tests:
class SoeNonRecursiveTest {
private final SoeNonRecursive soeNonRecursive = new SoeNonRecursive();
//Should be different for every case, or once generated class become
//"frozen" for javassist: http://www.javassist.org/tutorial/tutorial.html#read
private String generatedClassName;
#Test
void stackOverflowWithoutRecursion() {
generatedClassName = "Soe1";
final int numberOfLocalVarsToGenerate = 6000;
assertThrows(StackOverflowError.class, () -> soeNonRecursive
.createClassWithLotsOfLocalVars(generatedClassName, numberOfLocalVarsToGenerate));
}
#SneakyThrows
#Test
void methodGeneratedCorrectly() {
generatedClassName = "Soe2";
final int numberOfLocalVarsToGenerate = 6;
Class<?> generated = soeNonRecursive.createClassWithLotsOfLocalVars(generatedClassName, numberOfLocalVarsToGenerate);
//Arithmetic progression
long expected = Math.round((numberOfLocalVarsToGenerate - 1.0)/2 * numberOfLocalVarsToGenerate);
long actual = (long) generated.getDeclaredMethod(generatedMethodName).invoke(generated);
assertEquals(expected, actual);
}
}
EDIT:
The answer is incorrect, because it is one type of recursion. It is called indirect recursion https://en.wikipedia.org/wiki/Recursion_(computer_science)#Indirect_recursion.
I think the simplest way to do this without recursion is the following:
import java.util.LinkedList;
import java.util.List;
interface Handler {
void handle(Chain chain);
}
interface Chain {
void process();
}
class FirstHandler implements Handler {
#Override
public void handle(Chain chain) {
System.out.println("first handler");
chain.process();
}
}
class SecondHandler implements Handler {
#Override
public void handle(Chain chain) {
System.out.println("second handler");
chain.process();
}
}
class Runner implements Chain {
private List<Handler> handlers;
private int size = 5000; // change this parameter to avoid stackoverflowerror
private int n = 0;
public static void main(String[] args) {
Runner runner = new Runner();
runner.setHandlers();
runner.process();
}
private void setHandlers() {
handlers = new LinkedList<>();
int i = 0;
while (i < size) {
// there can be different implementations of handler interface
handlers.add(new FirstHandler());
handlers.add(new SecondHandler());
i += 2;
}
}
public void process() {
if (n < size) {
Handler handler = handlers.get(n++);
handler.handle(this);
}
}
}
At first glance this example looks a little crazy, but it's not as unrealistic as it seems.
The main idea of this approach is the chain of responsibility pattern. You can reproduce this exception in real life by implementing chain of responsibility pattern. For instance, you have some objects and every object after doing some logic call the next object in chain and pass the results of his job to the next one.
You can see this in java filter (javax.servlet.Filter).
I don't know detailed mechanism of working this class, but it calls the next filter in chain using doFilter method and after all filters/servlets processing request, it continue working in the same method below doFilter.
In other words it intercepts request/response before servlets and before sending response to a client.It is dangerous piece of code because all called methods are in the same stack at the same thread. Thus, it may initiate stackoverflow exception if the chain is too big or you call doFilter method on deep level that also provide the same situation. Perhaps, during debugging you might see chain of calls
in one thread and it potentially can be the cause of stackoverflowerror.
Also you can take chain of responsibility pattern example from links below and add collection of elements instead of several and you also will get stackoverflowerror.
Links with the pattern:
https://www.journaldev.com/1617/chain-of-responsibility-design-pattern-in-java
https://en.wikipedia.org/wiki/Chain-of-responsibility_pattern
I hope it was helpful for you.
Since the question is very interesting, I have tried to simplify the answer of hide :
public class Stackoverflow {
static class Handler {
void handle(Chain chain){
chain.process();
System.out.println("yeah");
}
}
static class Chain {
private List<Handler> handlers = new ArrayList<>();
private int n = 0;
private void setHandlers(int count) {
int i = 0;
while (i++ < count) {
handlers.add(new Handler());
}
}
public void process() {
if (n < handlers.size()) {
Handler handler = handlers.get(n++);
handler.handle(this);
}
}
}
public static void main(String[] args) {
Chain chain = new Chain();
chain.setHandlers(10000);
chain.process();
}
}
It's important to note that if stackoverflow occurs, the string "yeah" will never be output.
Of course we can do it :) . No recursion at all!
public static void main(String[] args) {
throw new StackOverflowError();
}
Looking at this answer below, not sure if this works for Java, but sounds like you can declare an array of pointers? Might be able to achieve Eric J's idea without requiring a generator.
Is it on the Stack or Heap?
int* x[LARGENUMBER]; // The addresses are held on the stack
int i; // On the stack
for(i = 0; i < LARGENUMBER; ++i)
x[i] = malloc(sizeof(int)*10); // Allocates memory on the heap

Getting number of calls to a mock

Assume I want to test code like this:
class ClassToTest
// UsedClass1 contains a method UsedClass2 thisMethod() {}
UsedClass1 foo;
void aMethod()
{
int max = new Random().nextInt(100);
for(i = 0; i < max; i++)
{
foo.thisMethod().thatMethod();
}
}
}
If I have a test like this:
ClassToTest test;
UsedClass1 uc1;
UsedClass2 uc2;
#Test
public void thingToTest() {
test = new ClassToTest();
uc1 = mock(UsedClass1.class);
uc2 = mock(UsedClass2.class);
when(uc1.thisMethod()).thenReturn(uc2);
when(uc2.thatMethod()).thenReturn(true);
test.aMethod();
// I would like to do this
verifyEquals(callsTo(uc1.thisMethod()), callsTo(uc2.thatMethod()));
}
How can I get the number of calls to uc1.thisMethod() and uc2.thatMethod() so I can check they were both called the same number of times?
You can do something like this:
YourService serviceMock = Mockito.mock(YourService.class);
// code using YourService
// details of all invocations including methods and arguments
Collection<Invocation> invocations = Mockito.mockingDetails(serviceMock).getInvocations();
// just a number of calls of any mock's methods
int numberOfCalls = invocations.size();
If you want only the invocations of certain method/param combination you, you can do so with
int specificMethodCall = Mockito.mockingDetails(serviceMock.myMethod(myParam)).getInvocations()
You could stub your methods, and increment a counter, like this:
final AtomicInteger countCall1 = new AtomicInteger();
Mockito.doAnswer(new Answer<UsedClass2>() {
#Override
public UsedClass2 answer(InvocationOnMock invocation) throws Throwable {
countCall1.incrementAndGet();
return uc2;
}
}).when(uc1).thisMethod();
If you know the number of times a method is suppoed to be called you can use the times() method of Mockito
//for example if had to be called 3 times
verify(uc1, times(3)).thisMethod();
verify(uc2, times(3)).thatMethod();
However, I now see that you call the method a random number of times, so this probably isn't the best answer unless you stub out the random number generator to always return an expected value.
You can use a custom VerificationMode to count the invocations, here you go:
public class InvocationCounter {
public static <T> T countInvocations(T mock, AtomicInteger count) {
return Mockito.verify(mock, new Counter(count));
}
private InvocationCounter(){}
private static class Counter implements VerificationInOrderMode, VerificationMode {
private final AtomicInteger count;
private Counter(AtomicInteger count) {
this.count = count;
}
public void verify(VerificationData data) {
count.set(data.getAllInvocations().size());
}
public void verifyInOrder(VerificationDataInOrder data) {
count.set(data.getAllInvocations().size());
}
#Override
public VerificationMode description(String description) {
return VerificationModeFactory.description(this, description);
}
}
}
And then use it like this (works also with void return types):
#Mock
private Function<String, Integer> callable;
AtomicInteger count= new AtomicInteger(); //here is the actual invocation count stored
countInvocations(callable,count).apply( anyString());
assertThat(count.get(),is(2));

Categories