Is it possible to sum up the nodes of a tree using Java 8 streams, if possible in a one liner ?
Here is a node class
public class Node
{
private int nodeNum;
ArrayList<Node> children = new ArrayList<>();
public Node(int num)
{
this.nodeNum = num;
}
public int getNodeNum()
{
return nodeNum;
}
public boolean addNode(Node node)
{
return children.add(node);
}
public ArrayList<Node> getNodes()
{
return this.children;
}
}
Normal way to solve this is using a recursion and sum up the node , like the code below.
int getNodeSum(Node node)
{
int total = 0;
if(node.children.isEmpty())
return node.getNodeNum();
else
{
for(Node tempNode:node.children)
{
total+= getNodeSum(tempNode);
}
return total+node.getNodeNum();
}
}
We can use streams to sum up the immediate child nodes but I'm not getting how to move deep and do it recursively using Streams.
This code only solves the problem to a single level. Any ideas?
total = list.stream().filter(Node -> node.children.isEmpty()).map(Node:: getNodeNum).reduce(node.getNodeNum(), (a,b) -> a+b);
One solution to your problem would be to use recursion along with Stream.flatMap.
First, you'd need to add the following helper method to your Node class:
public Stream<Node> allChildren() {
return Stream.concat(
Stream.of(this),
this.children.stream().flatMap(Node::allChildren)); // recursion here
}
This returns a Stream<Node> whose elements are this node and all its descendant nodes.
Then, you could rewrite your getNodeSum method as follows:
int getNodeSum(Node node) {
return node.allChildren()
.mapToInt(Node::getNodeNum)
.sum();
}
This uses the above defined Node.allChildren method along with the Stream.mapToInt and IntStream.sum methods to calculate the total sum.
Alternatively, you could have a Function<Node, Stream<Node>> descendants attribute in your Node class that performs the recursion in place:
private Function<Node, Stream<Node>> descendants =
node -> Stream.concat(
Stream.of(node),
node.children.stream()
.flatMap(this.descendants)); // recursion here: function invoked again
This is a recursive lambda expression, since the function you are defining is at both sides of the = sign. This kind of lambda expressions are allowed only as attributes of a class, i.e. you cannot assign a recursive lambda expression to a local variable.
With that recursive function in place, you could rewrite the allChildren method as follows:
public Stream<Node> allChildren() {
return descendants.apply(this);
}
Finally, the code for your getNodeSum method would be identical to the previous version:
int getNodeSum(Node node) {
return node.allChildren()
.mapToInt(Node::getNodeNum)
.sum();
}
Note: while this approach might result attractive for some people, it might have some drawbacks, i.e. now every instance of the Node class has the descendants attribute, despite not being needed at all. You could circumvect this i.e. by having a Tree class with this recursive function as an attribute, and Node being an inner class (with the descendants attribute removed).
You need to add recusive method for Node class, which wil be join child streams
public Stream<Node> recursiveConcat() {
return Stream.concat(
Stream.of(this),
children.stream().flatMap(Node::recursiveConcat));
}
Then do -
root.recusiveConcat().mapToInt(Node::getNodeNum).sum()
whole code
public class Node {
private int nodeNum;
ArrayList<Node> children = new ArrayList<>();
public Node(int num) {
this.nodeNum = num;
}
public int getNodeNum() {
return nodeNum;
}
public boolean addNode(Node node) {
return children.add(node);
}
public ArrayList<Node> getNodes() {
return this.children;
}
public Stream<Node> recursiveConcat() {
return Stream.concat(
Stream.of(this),
children.stream().flatMap(Node::recursiveConcat));
}
}
Node root = new Node(1);
Node node1 = new Node(2);
Node node2 = new Node(3);
Node node3 = new Node(4);
node2.addNode(node3);
node1.addNode(node2);
root.addNode(node1);
System.out.println(root.recursiveConcat().mapToInt(Node::getNodeNum).sum());
Related
I am trying to find the time complexity of the recursive function below. I've tried to draw the tree, but it is confusing because in the if condition the function is called once, and otherwise twice.
To give some context, the function is called on nodes of a tree. The task is to calculate the max rating of each node. The rule is that if you add some node to the rating you can't add it's children to the node, but if you don't add it than you can which children to add or don't.
Here is the function:
static int solve(Node node, boolean take) {
int result;
if(take) {
result = node.rating;
for(Node child : node.children) {
result += solve(child, false);
}
return result;
}
result = 0;
for(Node child : node.children) {
result += Math.max(solve(child, true), solve(child, false));
}
return result;
}
I know how to bind a property, but how can I bind the call of a fuction?
For example: I have a ObjectProperty which points to a file. Now, I want to bind the path to its folder? If the value of ObjectProperty is C:\\user\Desktop\text.txt, the bonding should point to C:\\user\Desktop.
I thought I can call getParentFile() within the binding.
There a many ways to map an ObjectProperty, take a look at the class Bindings.
(All examples assume that you have a ObjectProperty<File> file)
Bindings.createObjectBinding(Callable<T> func, Observable... dependencies)
ObjectBinding<File> parent = Bindings.createObjectBinding(() -> {
File f = file.getValue();
return f == null ? null : f.getParentFile();
}, file);
Bindings.select(ObservableValue<?> root, String... steps)
ObjectBinding<File> parent = Bindings.select(file, "parentFile");
This will print a warning on the error-stream when file is null.
You can also create your own mapping method (which is similar to createObjectBinding):
public static <T,R> ObjectBinding<R> map(ObjectProperty<T> property, Function<T,R> function) {
return new ObjectBinding<R>() {
{
bind(property);
}
#Override
protected R computeValue() {
return function.apply(property.getValue());
}
#Override
public void dispose() {
unbind(property);
}
};
}
And use it
ObjectBinding<File> parent = map(file, f -> f == null ? null : f.getParentFile());
I wanted to program a TableBrowser for a MYSQl Database in JavaFX.
My first problem is: i dont know which types i get back from the Database.
So i decided to wrap those types with a Wrapper-class.
To show these values on the GUI, i used the TableColumns setCellValueFactory-method, which
needs a value, that implements ObservableValue.
So i tried to implement the ObservableValue-interface.
But when i run the program it doesnt show the right Values.
TableBrowser after connecting to the Database
Has anyone an idea where i did wrong or knows a more recommended way to implement it ?
Here is the Part of the Code from the TableBrowser
/*
* this variable is used to iterate over the tableview's columns.
* It is a class variable, because it is not possible (for some reasons)
* to use a local variable while working with it in the context of Lambda-expressions
*/
int t = 0;
// those two variables are defined in the class Body
private final TableView<Entry> tableview = new TableView<>();
private final ObservableList<Entry> columndata = FXCollections.observableArrayList();
// the following Code is inside the Button's Actionlistener
for(int i = 1; i <= maxcol; i++) // adds a new TableColum for every colum in the DB
{
tableview.getColumns().add(new TableColumn<Entry, String>rsmd.getColumnName(i)));
}
// iterates over the ResultSet
while(rs.next())
{
// this is the dataset i put in my TableView
Entry row = new Entry(maxcol);
// for each Column i add the columnvalue to the current dataset
for(int i = 1; i <= maxcol; i++)
{
int type = rsmd.getColumnType(i);
Object value = rs.getObject(i);
row.setCellValue(i-1, type, value);
}
// adds a new dataset to the ObservableList<Entry>
columndata.add(row);
}
// puts all datasets in the TableView
tableview.setItems(columndata);
// iterates over all Columns
for(t = 0; t < tableview.getColumns().size(); t++)
{
// should set the CellValueFactory for each Column so it shows the data
/*
* I apologise if there a horrible mistake.
* I never worked with Lamda before and just copied it form an example page :)
*/
tableview.getColumns().get(t).setCellValueFactory(celldata -> celldata.getValue().getCellValue(t-1));
}
This is my Entry class, which is an inner Class in TableBrowserclass
/*
* should represent a Dataset.
* Has an array, which holdes every columnvalue as a WrapperType
*/
private class Entry
{
WrapperType<?>[] columns;
private Entry(int columncount)
{
columns = new WrapperType[columncount];
}
private WrapperType<?> getCellValue(int col)
{
return columns[col];
}
private void setCellValue(int col, int type, Object value)
{
columns[col] = MySQLTypeWrapper.getInstance().wrapType(type, value);
}
}
Here is the MySQLTypeWrapper class, which holds the WrapperType as an inner class
public class MySQLTypeWrapper
{
public WrapperType<?> wrapType(int type, Object Value)
{
Class<?> typeclass = toClass(type);
return new WrapperType<>(typeclass.cast(Value));
}
/*
* returns the appropriate class def for every database type
* Expl: VARCHAR returns String.class
*/
private static Class<?> toClass(int type) {...}
/*
* I copied the content of the of the overridden Methods from StringPropertyBase
* as i have clue how to implement ObservableValue
*/
class WrapperType<T> implements ObservableValue<WrapperType<T>>
{
private T value;
private ExpressionHelper<WrapperType<T>> helper = null;
private WrapperType(T value)
{
this.value = value;
}
#Override
public void addListener(InvalidationListener listener)
{
helper = ExpressionHelper.addListener(helper, this, listener);
}
#Override
public void removeListener(InvalidationListener listener)
{
helper = ExpressionHelper.removeListener(helper, listener);
}
#Override
public void addListener(ChangeListener<? super WrapperType<T>> listener)
{
helper = ExpressionHelper.addListener(helper, this, listener);
}
#Override
public void removeListener(ChangeListener<? super WrapperType<T>> listener)
{
helper = ExpressionHelper.removeListener(helper, listener);
}
#Override
public WrapperType<T> getValue()
{
return this;
}
public String toString()
{
return value.toString();
}
}
}
Thanks for your help in advance :)
As mentioned in the comments, your first problem was not using the TableView's Items property.
For the second part - one solution would be to create a helper method along the lines of
private <T> Callback<TableColumn.CellDataFeatures<Entry,T>,ObservableValue<T>> createCellFactory(int columnIndex) {
return celldata -> celldata.getValue().getCellValue(columnIndex);
}
and then change the loop to
// Now t can be a local variable, as it is not directly passed to the lambda.
for(int t = 0; t < tableview.getColumns().size(); t++)
{
// should set the CellValueFactory for each Column so it shows the data
tableview.getColumns().get(t).setCellValueFactory(createCellFactory(t));
}
Note that this time the variable passed to the lambda is a local effectively-final variable and not an instance variable, so the lambda is created with the correct value every time.
One last word of advice - are you sure you need this amount of generality? What I mean is - it is usually better to create a class to directly represent your DB structure with proper getters and setters, then you can use PropertyValueFactory.
..I'm building a binary tree where the root is given and the children are either root-3, root-2 or root-1 (that is, they hold those number of pennies). So 5 would have nodes of 2,3,4, and so on, until the leaves are 0. Here's my method for making such a tree. I don't understand why the method doesn't return the original node, in this case, the value should be 3.
Any guidance would be awesome.
public GameNode buildTree1(GameNode root){
int penn = root.getPennies();
if (penn < 0)
{
return null;
}
else {
root.print();
root.setLeft(buildTree1(new GameNode(penn-1)));
root.setMiddle(buildTree1(new GameNode(penn-2)));
root.setRight(buildTree1(new GameNode(penn-3)));
return root;
}
Get/Set Methods
public void setLeft(GameNode newNode) {
// TODO Auto-generated method stub
left = newNode;
}
Same for setMiddle and setRight;
A very simple & quick question on Java libraries: is there a ready-made class that implements a Queue with a fixed maximum size - i.e. it always allows addition of elements, but it will silently remove head elements to accomodate space for newly added elements.
Of course, it's trivial to implement it manually:
import java.util.LinkedList;
public class LimitedQueue<E> extends LinkedList<E> {
private int limit;
public LimitedQueue(int limit) {
this.limit = limit;
}
#Override
public boolean add(E o) {
super.add(o);
while (size() > limit) { super.remove(); }
return true;
}
}
As far as I see, there's no standard implementation in Java stdlibs, but may be there's one in Apache Commons or something like that?
Apache commons collections 4 has a CircularFifoQueue<> which is what you are looking for. Quoting the javadoc:
CircularFifoQueue is a first-in first-out queue with a fixed size that replaces its oldest element if full.
import java.util.Queue;
import org.apache.commons.collections4.queue.CircularFifoQueue;
Queue<Integer> fifo = new CircularFifoQueue<Integer>(2);
fifo.add(1);
fifo.add(2);
fifo.add(3);
System.out.println(fifo);
// Observe the result:
// [2, 3]
If you are using an older version of the Apache commons collections (3.x), you can use the CircularFifoBuffer which is basically the same thing without generics.
Update: updated answer following release of commons collections version 4 that supports generics.
Guava now has an EvictingQueue, a non-blocking queue which automatically evicts elements from the head of the queue when attempting to add new elements onto the queue and it is full.
import java.util.Queue;
import com.google.common.collect.EvictingQueue;
Queue<Integer> fifo = EvictingQueue.create(2);
fifo.add(1);
fifo.add(2);
fifo.add(3);
System.out.println(fifo);
// Observe the result:
// [2, 3]
I like #FractalizeR solution. But I would in addition keep and return the value from super.add(o)!
public class LimitedQueue<E> extends LinkedList<E> {
private int limit;
public LimitedQueue(int limit) {
this.limit = limit;
}
#Override
public boolean add(E o) {
boolean added = super.add(o);
while (added && size() > limit) {
super.remove();
}
return added;
}
}
Use composition not extends (yes I mean extends, as in a reference to the extends keyword in java and yes this is inheritance). Composition is superier because it completely shields your implementation, allowing you to change the implementation without impacting the users of your class.
I recommend trying something like this (I'm typing directly into this window, so buyer beware of syntax errors):
public LimitedSizeQueue implements Queue
{
private int maxSize;
private LinkedList storageArea;
public LimitedSizeQueue(final int maxSize)
{
this.maxSize = maxSize;
storageArea = new LinkedList();
}
public boolean offer(ElementType element)
{
if (storageArea.size() < maxSize)
{
storageArea.addFirst(element);
}
else
{
... remove last element;
storageArea.addFirst(element);
}
}
... the rest of this class
A better option (based on the answer by Asaf) might be to wrap the Apache Collections CircularFifoBuffer with a generic class. For example:
public LimitedSizeQueue<ElementType> implements Queue<ElementType>
{
private int maxSize;
private CircularFifoBuffer storageArea;
public LimitedSizeQueue(final int maxSize)
{
if (maxSize > 0)
{
this.maxSize = maxSize;
storateArea = new CircularFifoBuffer(maxSize);
}
else
{
throw new IllegalArgumentException("blah blah blah");
}
}
... implement the Queue interface using the CircularFifoBuffer class
}
The only thing I know that has limited space is the BlockingQueue interface (which is e.g. implemented by the ArrayBlockingQueue class) - but they do not remove the first element if filled, but instead block the put operation until space is free (removed by other thread).
To my knowledge your trivial implementation is the easiest way to get such an behaviour.
You can use a MinMaxPriorityQueue from Google Guava, from the javadoc:
A min-max priority queue can be configured with a maximum size. If so, each time the size of the queue exceeds that value, the queue automatically removes its greatest element according to its comparator (which might be the element that was just added). This is different from conventional bounded queues, which either block or reject new elements when full.
An LRUMap is another possibility, also from Apache Commons.
http://commons.apache.org/collections/apidocs/org/apache/commons/collections/map/LRUMap.html
Ok I'll share this option. This is a pretty performant option - it uses an array internally - and reuses entries. It's thread safe - and you can retrieve the contents as a List.
static class FixedSizeCircularReference<T> {
T[] entries
FixedSizeCircularReference(int size) {
this.entries = new Object[size] as T[]
this.size = size
}
int cur = 0
int size
synchronized void add(T entry) {
entries[cur++] = entry
if (cur >= size) {
cur = 0
}
}
List<T> asList() {
int c = cur
int s = size
T[] e = entries.collect() as T[]
List<T> list = new ArrayList<>()
int oldest = (c == s - 1) ? 0 : c
for (int i = 0; i < e.length; i++) {
def entry = e[oldest + i < s ? oldest + i : oldest + i - s]
if (entry) list.add(entry)
}
return list
}
}
public class ArrayLimitedQueue<E> extends ArrayDeque<E> {
private int limit;
public ArrayLimitedQueue(int limit) {
super(limit + 1);
this.limit = limit;
}
#Override
public boolean add(E o) {
boolean added = super.add(o);
while (added && size() > limit) {
super.remove();
}
return added;
}
#Override
public void addLast(E e) {
super.addLast(e);
while (size() > limit) {
super.removeLast();
}
}
#Override
public boolean offerLast(E e) {
boolean added = super.offerLast(e);
while (added && size() > limit) {
super.pollLast();
}
return added;
}
}