How to implement recursive method properly? - java

I have a list and this is how it looks like:
I have an arraylist<XmlProperty> myList.
My myList looks like this Image, so myList.get(0) ist the first row, myList.get(1) the second row etc.
An important point is that there are myList-Elements which are for example of Type "AdressType", so there are "children"-elements.
For this myList the Relations look like:
Stage = 0 Stage = 1 Stage = 2
Adress
-------------City
-------------Street
---------------------------StreetName
---------------------------HouseNumber
---------------------------Suffix
-------------PostalCode
So elements of Stage=1 are the children of the elements of the element of Stage=0.
You see it in the column "ChildNr" which elements are the children of the certain element.
So I want to invoke all methods with the objectValues but I have to take care about elements which have children because before I invoke them I have to invoke the children at first.
I tried to implement it, but I cannot implement the recursion properly.
public void buildChildrenObjectsRecursively(Object object, int xmlNumber, int fieldNr, int objectLength) throws InvocationTargetException, IllegalAccessException {
//amount of children-elements
if (objectLength != 0) {
if (myList.get(fieldNr).isHasChild() == false) {
myList.get(fieldNr).getCreateMethod().invoke(object, myList.get(fieldNr).getInstance());
fieldNr++;
} else { //recursive call
int childLength = getLengthOfObject(myList.get(fieldNr).getInstance());
buildChildrenObjectsRecursively(myList.get(fieldNr).getInstance(), xmlNumber, fieldNr + 1, childLength);
myList.get(fieldNr).getCreateMethod().invoke(object, allXmls.get(xmlNumber).get(fieldNr).getInstance());
}
objectLength--;
}
}
getInstance() is the Object in column "ObjectValue".
So where is my mistake?
All I want to do is:
invoke method on object
if there are children , then invoke methods on children-elements first, after that invoke method on object
UPDATE
I have to clarify it.
All what I want to do is:
invoke method object
if there are childre, the invoke methods on children-element first. after that invoke on object
This means for our example in the picture:
List with the order {1, 2, 3, 4, 5, 6, 7} should be {2, 4, 5, 6, 3, 7, 1}.
So in this order I can invoke the methods with a Loop easily.
So how can I do this?

The data struct define, you need use lombok if you using the Stage class :
import lombok.Data;
#Data
public class Stage{
private Integer number;
private Integer stageNumber;
private List<Integer> childNumber;
public static final class StageBuilder {
private Integer number;
private Integer stageNumber;
private List<Integer> childNumber;
private StageBuilder() {
}
public static StageBuilder aStage() {
return new StageBuilder();
}
public StageBuilder withNumber(Integer number) {
this.number = number;
return this;
}
public StageBuilder withStageNumber(Integer stageNumber) {
this.stageNumber = stageNumber;
return this;
}
public StageBuilder withChildNumber(List<Integer> childNumber) {
this.childNumber = childNumber;
return this;
}
public Stage build() {
Stage stage = new Stage();
stage.setNumber(number);
stage.setStageNumber(stageNumber);
stage.setChildNumber(childNumber);
return stage;
}
}
}
The implement of the stage, just using java8 to sort by the stage number:
public class StageTest extends TestCase {
public void test() {
Stage stage1 = Stage.StageBuilder.aStage().withNumber(1).withStageNumber(0).withChildNumber(Arrays.asList(2, 3, 7)).build();
Stage stage2 = Stage.StageBuilder.aStage().withNumber(2).withStageNumber(1).build();
Stage stage3 = Stage.StageBuilder.aStage().withNumber(3).withStageNumber(1).withChildNumber(Arrays.asList(4, 5, 6)).build();
Stage stage4 = Stage.StageBuilder.aStage().withNumber(4).withStageNumber(2).build();
Stage stage5 = Stage.StageBuilder.aStage().withNumber(5).withStageNumber(2).build();
Stage stage6 = Stage.StageBuilder.aStage().withNumber(6).withStageNumber(2).build();
Stage stage7 = Stage.StageBuilder.aStage().withNumber(7).withStageNumber(1).build();
List<Stage> stageList = Arrays.asList(stage1, stage2, stage3, stage4, stage5, stage6, stage7);
stageList.sort((o1, o2) -> o2.getStageNumber() - o1.getStageNumber());
stageList.forEach(item -> System.out.println(item.getNumber()));
}
}

Related

How to use BinaryHandler correctly in Microstream to store volatile array of longs?

I tried to store Eclipse Collection's LongArrayList (https://www.eclipse.org/collections/) with Microstream, but due to it's "items" field being transient this didn't work out of the box.
So what I did was to create a new class PersistableLongArrayList like this:
public class PersistableLongArrayList extends LongArrayList {
static BinaryTypeHandler<PersistableLongArrayList> provideTypeHandler() {
return Binary.TypeHandler(PersistableLongArrayList.class,
Binary.Field_int(
"size",
list -> list.size,
(list, value) -> list.size = value
),
Binary.Field(
long[].class, "items",
list -> list.items,
(list, value) -> list.items = value
)
);
}
}
The items field is now not null when loaded from a stored instance, however if I change the value afterwards and call storage.store(list), shutdown the db and restart it the new value is not stored, only size is stored correctly.
I've added a very simple example that shows this behavior:
public class SimpleTest {
private PersistableLongArrayList root;
public static void main(String[] args) {
try {
SimpleTest t = new SimpleTest();
// DB erstellen
EmbeddedStorageManager storage = t.startDB();
// modify the list
t.root.add(t.root.size() + 1);
storage.store(t.root);
// stop DB
t.stopDB(storage);
// restart DB
storage = t.startDB();
// show root element
System.out.println(t.root);
// Observed behavior: list "grows" from s.th. like this: [1] to s.th. like this [1, 0, 0, 0] after several runs (Probably only size grows and is stored correctly and therefore the fields up to "size" are printed but empty)
// Expected beahvior: list starts with [1] and grows to something like this [1, 2, 3, 4] after several runs
} catch (Throwable t) {
t.printStackTrace();
} finally {
System.exit(0);
}
}
private EmbeddedStorageManager startDB() {
EmbeddedStorageManager storageManager = EmbeddedStorage.start();
if(storageManager.root() == null) {
PersistableLongArrayList list = new PersistableLongArrayList();
storageManager.setRoot(list);
storageManager.storeRoot();
root = list;
} else {
root = (PersistableLongArrayList)storageManager.root();
}
return storageManager;
}
private void stopDB(EmbeddedStorageManager storageManager) {
storageManager.shutdown();
}
}
Probably I just misunderstood how to use the custom BinaryHandler correctly, but I have no idea what to change right now.
Any advice is appreciated :)
Kind regards,
Thomas
Using a custom PersistenceEagerStoringFieldEvaluator and PersistenceFieldEvaluator it is possible to persist the LongArrayList directly:
public class PersistenceFieldEvaluatorCustom implements PersistenceFieldEvaluator {
#Override
public boolean applies(final Class<?> entityType, final Field field) {
//return true if field should be persisted, false if not
if(entityType == org.eclipse.collections.impl.list.mutable.primitive.LongArrayList.class && field.getName().equals("items")) {
return true;
}
//default: return false if field has the transient modifier
return !XReflect.isTransient(field);
}
}
public class PersistenceEagerStoringFieldEvaluatorCustom implements PersistenceEagerStoringFieldEvaluator {
#Override
public boolean isEagerStoring(final Class<?> t, final Field u) {
//return true if field should be persisted at every store
if(t == org.eclipse.collections.impl.list.mutable.primitive.LongArrayList.class && u.getName().equals("items")) {
return true;
}
return false;
}
}
Setup:
final EmbeddedStorageManager s = EmbeddedStorage.Foundation()
.onConnectionFoundation(
c->{ c.setFieldEvaluatorPersistable(new PersistenceFieldEvaluatorCustom());
c.setReferenceFieldEagerEvaluator(new PersistenceEagerStoringFieldEvaluatorCustom());
})
.start();
best regards
see https://github.com/microstream-one/microstream/discussions/247 for some more details

How does java lambdas external references work?

I'm wondering how does lambdas external references work. Let me explain:
Suppose i have this supplier implementation and this model class :
public class TestSupplierImpl implements Supplier<Boolean> {
public Predicate<Integer> predicate;
public TestSupplierModel model;
public TestSupplierImpl() {
this.predicate = i -> model.something.equals(i);
}
#Override
public Boolean get() {
return predicate.test(3);
}
}
class TestSupplierModel {
public Integer something;
public TestSupplierModel(Integer something) {
this.something = something;
}
}
Then i execute the following code:
TestSupplierImpl test = new TestSupplierImpl(); // line 1
test.model = new TestSupplierModel(3); // line 2
Boolean resultado = test.get(); // line 3
Line 1: creating a new instance of TestSupplierImpl. This new instance's predicate has a null reference of model. This makes sense because at the moment of creation of the predicate, model reference is null.
Line 2: assign to variable model a new instance of TestSupplierModel.
Line 3: test.predicate now has model reference with the new assigned value. Why is this ?
I don't understand why ,when I changed model reference, the predicate updates its model reference to the new one. How is that ?
Thanks in advance !
Does it make sense if you rewrote your TestSupplierImpl() constructor as follows?
public Predicate<Integer> predicate;
public TestSupplierModel model;
public TestSupplierImpl() {
// same effect as this.predicate = i -> model.something.equals(i);
this.predicate = new Predicate<Integer>() {
public boolean test(Integer i) {
return model.something.equals(i);
}
};
}
#Override
public Boolean get() {
return predicate.test(3);
}
So here is the order of things.
// the constructor is run and the test method defined BUT NOT executed.
TestSupplierImpl test = new TestSupplierImpl(); // line 1
// Now you define model
test.model = new TestSupplierModel(3); // line 2
// Then you execute the predictate via get()
Boolean resultado = test.get(); // line 3
model and something aren't required until you issue the get() method. By that time they are already defined.

Is there a way I could print these IDs in ascending order of their versions?

I have an input set that has x number of IDs with their corresponding versions. An id can have multiple versions but they all will be in ascending order in the input set. I use Executor service that takes in certain number of threads, and waits for some time (to simulate I/O delay) and prints the ID and version to console. I want to make sure The console prints all the ID versions in ascending order. I can only modify the add() function and the run method, and add class variables if need be.
I tried using Hashmaps to set the id values to true whenever a thread is working on a dataitem with the specified id. Everytime the run method calls, it checks if the map has that ID value to be true; if so, it is supposed to wait. if not, execute. There is something wrong with the code, so it's mainly an issue with understanding the methods, i think.
The data item class which will be the input. (A set of Dataitems)
public class DataItem {
private int id;
private int version;
private long amount;
public DataItem(int id, int version, long amount) {
super();
this.id = id;
this.version = version;
this.amount = amount;
}
}
The Feedprocessor class that adds threads to the pool
public class FeedProcessor extends AbstractFeedProcessor {
public Map<Integer,Boolean> lock_set = new HashMap<Integer,Boolean>();
private ExecutorService threadPool = Executors.newFixedThreadPool(3);
public FeedProcessor() {
}
public void add(DataItem item) {
threadPool.submit(new ProcessTask(item));
}
}
The processtask class that implements runnable
class ProcessTask implements Runnable {
private DataItem item;
ProcessTask(DataItem item) {
this.item = item;
}
#Override
public void run(){
saveItem(item);
}
}
The main function will call the following :
static final DataItem[] dataList2 = {
new DataItem(10000, 1, 100),
new DataItem(10001, 1, 50),
new DataItem(10000, 2, 200),
new DataItem(10001, 2, 51),
new DataItem(10000, 3, 300),
new DataItem(10001, 3, 52),
new DataItem(10000, 4, 400),
new DataItem(10001, 4, 53)
};
static void test1() {
long start = System.currentTimeMillis();
System.out.println("====== Test 1 ======");;
FeedProcessor processor = new FeedProcessor();
for(DataItem item : dataList1) {
processor.add(item);
}
processor.shutdown();
System.out.println("Test 1 took " + (System.currentTimeMillis()-start));
}
Currently the results are not in ascending order of their versions, that's the goal.

How To Do Recursive Observable Call in RxJava?

I am quite new to RxJava (and Reactive paradigm in general), so please bear with me.
Suppose I have this News and this nested Comment data structure:
public class News {
public int id;
public int[] commentIds; //only top level comments
public News(int id, int[] commentIds) {
this.id = id;
this.commentIds = commentIds;
}
}
public class Comment {
public int id;
public int parentId; //ID of parent News or parent comment
public int[] childIds;
public Comment(int id, int parentId, int[] childIds) {
this.id = id;
this.parentId = parentId;
this.childIds = childIds;
}
}
and suppose I have this API endpoint:
getComments(int commentId) //return Observable<Comment> for Comment with ID commentId
Now, let's assume:
getComments(1); //will return Comment(1, 99, [3,4])
getComments(2); //will return Comment(2, 99, [5,6])
getComments(3); //will return Comment(3, 1, [])
getComments(4); //will return Comment(4, 1, [])
getComments(5); //will return Comment(5, 2, [])
getComments(6); //will return Comment(6, 2, [])
**
Now, if I have News n = News(99, [1,2]), how do I get all of its children comment recursively? i.e. to get comments with ID [1,2,3,4,5,6]?
**
I have searched and stumbled upon this: https://jkschneider.github.io/blog/2014/recursive-observables-with-rxjava.html
This is the recursion function:
public class FileRecursion {
static Observable<File> listFiles(File f) {
if(f.isDirectory())
return Observable.from(f.listFiles()).flatMap(FileRecursion::listFiles);
return Observable.just(f);
}
public static void main(String[] args) {
Observable.just(new File("/Users/joschneider/Desktop"))
.flatMap(FileRecursion::listFiles)
.subscribe(f -> System.out.println(f.getAbsolutePath()));
}
}
It shows an example on how to do recursive observable calls, but the inner function (f.listFiles()) is a blocking operation (doesn't return another Observable). In my case, the inner function (getComments) is a non-blocking function that returns another Observables. How do I do that?
Any help will be much appreciated.
This does practically the same thing described in the article:
Observable<Comment> getInnerComments(Comment comment) {
if (comment.childIds.length > 0)
return Observable.merge(
Observable.just(comment),
Observable.from(comment.childIds)
.flatMap(id -> getComments(id))
.flatMap(this::getInnerComments));
return Observable.just(comment);
}
public static void main(String[] args) {
getComments(1)
.flatMap(this::getInnerComments)
.subscribe(c -> System.out.println(comment.toString()));
}
I start with the comment with id = 1, then I pass it to getInnerComments(). The getInnerComments() checks if the comment has children. If it does, it iterates over every child id (Observable#from) and loads every child with your getComments(int) API. Then every child is passed to the getInnerComments() to do the same procedure. If a comment doesn't have children, it is immediately returned using Observable#just.
This is pseudo-code and it wasn't tested, but you should get the idea.
Below is an example of how to get all comments and then aggregate them to one List<Comment>.
getNews(99)
.flatMap(news -> Observable.from(news.commentIds))
.flatMap(commentId -> getComments(commentId))
.flatMap(comment -> getInnerComments(comment))
.toList()
.subscribe(commentList -> { });

Testing class with ArrayList private member

I have a Java class with following implementation:
class Some {
private ArrayList<SomeObject> list = new...
public void addToList(Long t) {
SomeObject so = new SomeObject(new Date, t)
list.add(so)
}
private float fun1(ArrayList<SomeObject> x) {
//some operations on list "list",
//res - result of float calculations based on list "x"
return res
}
public float publicFun() {
//some other operations on private list "list"
return fun1(list);
}
The question is how to test function publicFun() using Mockito, PowerMock or other testing tool ? To run this public function I have to mock private List but how can I do it ?
In this example there are several problems caused by unwelcome dependencies:
1 new Date()
To solve it I suggest to introduce new interface
interface CurrentTimeProvider {
Date getCurrentDate();
}
Implementation is obvious (I skip it for briefness)
2 Is new ArrayList()
You can replace it with you own interface (containing only method you
need)
You can mock ArrayList itself
You can use real impl of ArrayList and test it altogether
In result we get something like this:
class Some {
private CurrentTimeProvider timeProvider;
private ArrayList<SomeObject> list = new ArrayList<SomeObject>();
public void setTimeProvider(CurrentTimeProvider timeProvider) {
this.timeProvider = timeProvider;
}
public void addToList(Long t) {
SomeObject so = new SomeObject(timeProvider.getCurrentDate(), t)
list.add(so)
}
public float publicFun() {
//some other operations on private list "list"
return fun1(list);
}
And test look look this:
CurrentTimeProvider timeProvider = mock(CurrentTimeProvider.class);
Some some = new Some();
some.setTimeProvider(timeProvider);
when(timeProvider.getCurrentDate).thenReturn(mock(Date.class));
//Invoke you method
some.publicFun();
//Put assert and verify here

Categories

Resources