I am using JavaFX from 2 years back. Now i am creating spreadsheet like control using JavaFX.For creating control i am using TableView and ScrollPane with ListView control for Spreadsheet Row header as JavaFX do not provide support for row headers.Everything is working fine except one thing when i scroll table , initially table and scrollpane rows scroll in sync but after some scroll its starting mismatch.I have attached the screen shots of the same.
1)Initial screen without scroll
2)Screen after some scroll
Following are the code snippet for this control which i have pasted in pastebin.
1)Cells.java
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Cells extends Application {
public void start(Stage stage) {
stage.setScene(new Scene(new SpreadSheet(100, 26)));
stage.setTitle("Cells");
stage.setWidth(400);
stage.setHeight(400);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
2)SpreadSheet.java
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.input.ScrollEvent;
import javafx.scene.layout.HBox;
public class SpreadSheet extends HBox {
public SpreadSheet(int height, int width) {
super();
Model model = new Model(height, width);
TableView<ObservableList<Model.Cell>> table = new TableView<>();
table.setEditable(true);
table.setItems(model.getCellsAsObservableList());
for (char w = 'A'; w < 'A'+width; w++) {
TableColumn<ObservableList<Model.Cell>, String> column = new TableColumn<>(w+"");
column.setSortable(false);
column.setMinWidth(50);
column.setCellFactory(TextFieldTableCell.forTableColumn());
final char w0 = w;
column.setCellValueFactory(param -> param.getValue().get(w0-'A').text);
column.setOnEditStart(event -> {
int row = event.getTablePosition().getRow();
int col = event.getTablePosition().getColumn();
Model.Cell c = model.getCells()[row][col];
c.setShowUserData(true);
});
column.setOnEditCommit(event -> {
int row = event.getTablePosition().getRow();
int col = event.getTablePosition().getColumn();
Model.Cell c = model.getCells()[row][col];
System.out.println("Hello");
c.userData.set(event.getNewValue());
c.setShowUserData(false);
});
table.getColumns().add(column);
}
ListView<String> rowHeaders = new ListView<>();
rowHeaders.getItems().add("");
for (int i = 0; i < height; i++) {
rowHeaders.getItems().add(i+"");
}
ScrollPane scrolledRowHeaders = new ScrollPane(rowHeaders);
scrolledRowHeaders.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
scrolledRowHeaders.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
table.getChildrenUnmodifiable().addListener((ListChangeListener<Node>) c -> {
ScrollBar vbarTable = (ScrollBar) table.lookup(".scroll-bar:vertical");
ScrollBar vbarRowHeaders = (ScrollBar) scrolledRowHeaders.lookup(".scroll-bar:vertical");
if (vbarRowHeaders != null && vbarTable != null)
vbarTable.valueProperty().bindBidirectional(vbarRowHeaders.valueProperty());
});
getChildren().addAll(scrolledRowHeaders, table);
}
}
3)Model.java
import java.util.List;
import javafx.beans.binding.Binding;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
class Model {
private Cell[][] cells;
Model(int height, int width) {
cells = new Cell[height][width];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
cells[i][j] = new Cell();
}
}
}
public Cell[][] getCells() {
return cells;
}
public ObservableList<ObservableList<Cell>> getCellsAsObservableList() {
ObservableList<ObservableList<Cell>> cs = FXCollections.observableArrayList();
for (int i = 0; i < cells.length; i++) {
cs.add(FXCollections.observableArrayList());
for (int j = 0; j < cells[i].length; j++) {
cs.get(i).add(cells[i][j]);
}
}
return cs;
}
class Cell {
public final StringProperty userData = new SimpleStringProperty("");
public final StringProperty text = new SimpleStringProperty("");
ObservableValue<Double>[] toArray(List<ObservableValue<Double>> l) {
return l.toArray(new ObservableValue[l.size()]);
}
// Has same problem
// public ObservableValue<Double> value = EasyBind.map(userData, Parser::parse)
// .flatMap(f -> Bindings.createObjectBinding(() -> f.eval(Model.this), toArray(f.getReferences(Model.this))));
// Has same problem
public ObservableValue<Double> value =
Bindings.createObjectBinding(() -> {
System.out.println(System.currentTimeMillis());
Formula f = Parser.parse(userData.get());
ObservableValue<Double>[] fs = toArray(f.getReferences(Model.this));
Binding<Double> d = Bindings.createObjectBinding(() -> {
double v = f.eval(Model.this);
// text.set(String.valueOf(v));
return v;
}, fs);
d.addListener((v, o, n) -> {
// ???
});
return d.getValue();
}, userData);
public void setShowUserData(Boolean b) {
if (b) text.setValue(userData.get());
else text.setValue(String.valueOf(value.getValue()));
}
}
}
4)Parser.java
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class Parser {
private static Parser instance = new Parser();
private static Tokenizer tokenizer;
static {
tokenizer = new Tokenizer();
tokenizer.add("[a-zA-Z_]\\d+", Token.CELL);
tokenizer.add("[a-zA-Z_]\\w*", Token.IDENT);
tokenizer.add("-?\\d+(\\.\\d*)?", Token.DECIMAL);
tokenizer.add("=", Token.EQUALS);
tokenizer.add(",", Token.COMMA);
tokenizer.add(":", Token.COLON);
tokenizer.add("\\(", Token.OPEN_BRACKET);
tokenizer.add("\\)", Token.CLOSE_BRACKET);
}
public static Formula parse(String formulaString) {
return instance.parseFormula(formulaString);
}
String formulaString;
LinkedList<Token> tokens;
Token lookahead;
private Parser() {}
private Formula parseFormula(String formulaString) {
this.formulaString = formulaString;
try {
tokenizer.tokenize(formulaString.replaceAll("\\s+",""));
} catch (ParseError e) {
System.out.println(e.getMessage());
}
this.tokens = tokenizer.getTokens();
if (tokens.isEmpty()) return Formula.Empty;
lookahead = this.tokens.getFirst();
return formula();
}
private Formula formula() {
switch(lookahead.token) {
case Token.DECIMAL:
String n = lookahead.sequence;
nextToken();
return new Number(Double.parseDouble(n));
case Token.EQUALS:
nextToken();
return expression();
case Token.EPSILON:
return Formula.Empty;
default:
return new Textual(formulaString);
}
}
private Formula expression() {
switch(lookahead.token) {
case Token.CELL:
int c = lookahead.sequence.charAt(0) - 'A';
int r = Integer.parseInt(lookahead.sequence.substring(1));
nextToken();
if (lookahead.token == Token.COLON) { // Range
nextToken();
if (lookahead.token == Token.CELL) {
int c2 = lookahead.sequence.charAt(0) - 'A';
int r2 = Integer.parseInt(lookahead.sequence.substring(1));
nextToken();
return new Range(new Coord(r, c), new Coord(r2, c2));
} else {
throw new ParseError("Incorrect Range: " + lookahead.sequence);
}
} else {
return new Coord(r, c);
}
case Token.DECIMAL:
Double d = Double.parseDouble(lookahead.sequence);
nextToken();
return new Number(d);
case Token.IDENT:
return application();
default:
throw new ParseError("Incorrect Expression: " + lookahead.sequence);
}
}
private Formula application() {
String opName = lookahead.sequence;
nextToken();
if (lookahead.token != Token.OPEN_BRACKET)
throw new ParseError("No opening bracket: " + opName);
nextToken();
List<Formula> args = new ArrayList<Formula>();
while (true) {
if (lookahead.token == Token.EPSILON)
throw new ParseError("No closing bracket");
args.add(expression());
if (lookahead.token == Token.COMMA) nextToken();
if (lookahead.token == Token.CLOSE_BRACKET)
return new Application(opName, args);
}
}
private void nextToken() {
tokens.pop();
if (tokens.isEmpty()) lookahead = new Token(Token.EPSILON, "");
else lookahead = tokens.getFirst();
}
}
class ParseError extends RuntimeException {
ParseError(String message) {
super(message);
}
}
class Token {
public static final int EPSILON = 0;
public static final int EQUALS = 1;
public static final int IDENT = 2;
public static final int DECIMAL = 3;
public static final int OPEN_BRACKET = 4;
public static final int CLOSE_BRACKET = 5;
public static final int COMMA = 6;
public static final int COLON = 7;
public static final int CELL = 8;
public final int token;
public final String sequence;
public Token(int token, String sequence) {
this.token = token;
this.sequence = sequence;
}
}
class Tokenizer {
private LinkedList<TokenInfo> tokenInfos;
private LinkedList<Token> tokens;
public Tokenizer() {
tokenInfos = new LinkedList<TokenInfo>();
tokens = new LinkedList<Token>();
}
public void add(String regex, int token) {
tokenInfos.add(new TokenInfo(Pattern.compile("^("+regex+")"), token));
}
public void tokenize(String s) {
tokens.clear();
while (!s.equals("")) {
boolean match = false;
for (TokenInfo info : tokenInfos) {
Matcher m = info.regex.matcher(s);
if (m.find()) {
match = true;
String tok = m.group().trim();
tokens.add(new Token(info.token, tok));
s = m.replaceFirst("");
break;
}
}
if (!match) throw new ParseError("Unexpected char in input: " + s);
}
}
public LinkedList<Token> getTokens() {
return tokens;
}
private static class TokenInfo {
public final Pattern regex;
public final int token;
public TokenInfo(Pattern regex, int token) {
super();
this.regex = regex;
this.token = token;
}
}
}
5)Formula.java
import javafx.beans.value.ObservableValue;
import javafx.scene.control.Cell;
import java.util.*;
abstract class Formula {
public static final Formula Empty = new Textual("");
public double eval(Model env) { return 0.0; }
public List<ObservableValue<Double>> getReferences(Model env) { return Collections.emptyList(); }
}
class Textual extends Formula {
String value;
public Textual(String value) {
this.value = value;
}
public String toString() {
return value;
}
}
class Number extends Formula {
double value;
public Number(double value) {
this.value = value;
}
public String toString() {
return String.valueOf(value);
}
public double eval(Model env) {
return value;
}
}
class Coord extends Formula {
int row, column;
public Coord(int row, int column) {
this.row = row;
this.column = column;
}
public String toString() {
return ((char)('A'+column))+""+row;
}
public double eval(Model env) {
return env.getCells()[row][column].value.getValue();
}
public List<ObservableValue<Double>> getReferences(Model env) {
List<ObservableValue<Double>> result = new ArrayList<>(1);
result.add(env.getCells()[row][column].value);
return result;
}
}
class Range extends Formula {
Coord coord1, coord2;
public Range(Coord coord1, Coord coord2) {
this.coord1 = coord1; this.coord2 = coord2;
}
public String toString() {
return String.valueOf(coord1)+":"+String.valueOf(coord2);
}
public double eval(Model env) {
throw new RuntimeException("Range cannot be evaluated!");
}
public List<ObservableValue<Double>> getReferences(Model env) {
List<ObservableValue<Double>> result = new ArrayList<>();
for (int r = coord1.row; r <= coord2.row; r++) {
for (int c = coord1.column; c <= coord2.column; c++) {
result.add(env.getCells()[r][c].value);
}
}
return result;
}
}
class Application extends Formula {
String function;
List<Formula> arguments;
public Application(String function, List<Formula> arguments) {
this.function = function;
this.arguments = arguments;
}
public String toString() {
StringBuilder t = new StringBuilder();
t.append(function);
t.append("(");
for (int i = 0; i < arguments.size()-1; i ++) {
t.append(arguments.get(i).toString());
t.append(", ");
}
if (!arguments.isEmpty()) t.append(arguments.get(arguments.size()-1).toString());
t.append(")");
return t.toString();
}
public double eval(Model env) {
try {
List<Double> argvals = evalList(arguments, env);
return opTable.get(function).eval(argvals);
} catch(Exception e) {
return Double.NaN;
}
}
public List<ObservableValue<Double>> getReferences(Model env) {
List<ObservableValue<Double>> result = new ArrayList<>();
for (Formula argument : arguments) {
result.addAll(argument.getReferences(env));
}
return result;
}
private static List<Double> evalList(List<Formula> args, Model env) {
List<Double> result = new ArrayList<>();
for (Formula f : args) {
if (f instanceof Range) {
for (ObservableValue<Double> c : f.getReferences(env)) {
result.add(c.getValue());
}
} else {
result.add(f.eval(env));
}
}
return result;
}
private static Map<String, Op> opTable = new HashMap<>();
static {
opTable.put("add", vals -> vals.get(0) + vals.get(1));
opTable.put("sub", vals -> vals.get(0) - vals.get(1));
opTable.put("div", vals -> vals.get(0) / vals.get(1));
opTable.put("mul", vals -> vals.get(0) * vals.get(1));
opTable.put("mod", vals -> vals.get(0) % vals.get(1));
opTable.put("sum", vals -> {
double accum = 0;
for (Double i : vals) {
accum += i;
}
return accum;
});
opTable.put("prod", vals -> {
double accum = 1;
for (Double i : vals) {
accum *= i;
}
return accum;
});
}
private static interface Op {
public double eval(List<Double> vals);
}
}
Try this
For your ListView get your VBar and bind it with your TableView VBar and your alignment will be intact.
To get your ListView VBar run this code same for TableView VBar
VirtualFlow tvVF = (VirtualFlow) TableView.lookup("#virtual-flow");
for (Node n : tvVF.getChildrenUnmodifiable()) {
if (n.getClass().isAssignableFrom(VirtualScrollBar.class)) {
VirtualScrollBar table_vsb = (VirtualScrollBar) n;
if (tvVF.getWidth() - table_vsb.getWidth() > tvVF.getWidth() / 2) {
//table_vsb is your Vertical bar for the TableView
....//close braces
VirtualFlow lvVF = (VirtualFlow) ListView.lookup("#virtual-flow");
// we do the same for listview
for (Node c : lvVF.getChildrenUnmodifiable()) {
if (c.getClass().isAssignableFrom(VirtualScrollBar.class)) {
VirtualScrollBar list_vsb = (VirtualScrollBar) c;
if (tvVF.getWidth() - vsb.getWidth() > tvVF.getWidth() / 2) {
//list_vsb is your vbar for the listview
now since you have your two VBar's bind the ListView's to the TableView like this
list_vsb.valueProperty().bind(table_vsb.valueProperty());
Please note that you need to call these codes after a full layout, or when Stage.show(); is called - to be safe
Hope its lucid and helps
EDIT
[][]3
it does work for me :)
Related
I have this class:
package metodo_java8_moderno;
import java.util.ArrayList;
import java.util.List;
public class SingleThreadClass {
public List<Object> editAndAdd(List<List<Long>> matrix){
Long limit = (long) matrix.get(0).size()*matrix.size()/2;
List<Long> numbers = new ArrayList<>();
for(int i=0; i<matrix.get(0).size(); i++){
for(int j=0; j<matrix.size(); j++){
if(matrix.get(j).get(i).longValue() <= limit){
numbers.add(matrix.get(j).get(i));
matrix.get(j).set(i,null);
}
}
}
List<Object> objectList = new ArrayList<>();
objectList.add(matrix);
objectList.add(numbers);
return objectList;
}
}
I want to parallel only the following piece by exploiting all the cores of my CPU:
for(int j=0; j<matrix.size(); j++){
if(matrix.get(j).get(i).longValue() <= limit){
numbers.add(matrix.get(j).get(i));
matrix.get(j).set(i,null);
}
}
I get an error and I believe it is due to the sharing of objects between different threads.
I post all the code of my work:
ElementMutator.java
package metodo_java8_moderno;
#FunctionalInterface
public interface ElementMutator<T> {
void apply(int i);
}
ForkJoinListMutator.java
package metodo_java8_moderno;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
public class ForkJoinListMutator {
public static final int DEFAULT_SEQ_THRESHOLD = 10000;
private static final ForkJoinListMutator defaultInstance = new ForkJoinListMutator(ForkJoinPool.commonPool());
private final ForkJoinPool forkJoinPool;
public ForkJoinListMutator(ForkJoinPool forkJoinPool) {
this.forkJoinPool = forkJoinPool;
}
public static ForkJoinListMutator getDefault() {
return defaultInstance;
}
public <T> void mutate(List<T> list, ElementMutator<T> mutator) {
mutate(list, DEFAULT_SEQ_THRESHOLD, mutator);
}
public <T> void mutate(List<T> list, int seqThreshold, ElementMutator<T> mutator) {
MutateTask<T> mainTask = new MutateTask<>(list, seqThreshold, mutator);
forkJoinPool.invoke(mainTask);
}
private static class MutateTask<T> extends RecursiveAction {
private final List<T> list;
private final int start;
private final int end;
private final int seqThreshold;
private final ElementMutator<T> mutator;
public MutateTask(List<T> list, int seqThreshold, ElementMutator<T> mutator) {
this(list, 0, list.size(), seqThreshold, mutator);
}
public MutateTask(List<T> list, int start, int end, int seqThreshold, ElementMutator<T> mutator) {
this.list = list;
this.start = start;
this.end = end;
this.seqThreshold = seqThreshold;
this.mutator = mutator;
}
#Override
protected void compute() {
final int length = end - start;
if (length <= seqThreshold) {
computeSequentially();
} else {
MutateTask<T> leftTask = new MutateTask<>(list, start, start+length/2, seqThreshold, mutator);
leftTask.fork();
leftTask.join();
MutateTask<T> rightTask = new MutateTask<>(list, start+length/2, end, seqThreshold, mutator);
rightTask.compute();
}
}
private void computeSequentially() {
for (int i = start; i < end; i++) {
mutator.apply(i);
}
}
}
}
ForkJoinListMutatorExample.java
package metodo_java8_moderno;
import java.util.List;
public class ForkJoinListMutatorExample {
public static void main(String args[]) {
GenerateMatrix generateMatrix = new GenerateMatrix();
List<List<Long>> matrix = generateMatrix.generate(3,4);
System.out.println(matrix);
long t1 = System.nanoTime();
SingleThreadClass singleThreadClass = new SingleThreadClass();
List<Object> output = singleThreadClass.editAndAdd(matrix);
long t2 = System.nanoTime();
System.out.println("Time taken single thread process: " + (t2-t1)/100000000);
List<List<Long>> newMatrix = (List<List<Long>>) output.get(0);
List<Long> numbers = (List<Long>) output.get(1);
System.out.println(newMatrix);
System.out.println(numbers);
t1 = System.nanoTime();
MultiThreadClass multiThreadClass = new MultiThreadClass();
output = multiThreadClass.editAndAdd(matrix);
t2 = System.nanoTime();
System.out.println("Time taken multi thread process: " + (t2-t1)/100000000);
List<List<Long>> newMatrix2 = (List<List<Long>>) output.get(0);
List<Long> numbers2 = (List<Long>) output.get(1);
System.out.println(newMatrix2);
System.out.println(numbers2);
}
}
GenerateMatrix.java
package metodo_java8_moderno;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class GenerateMatrix {
public List<List<Long>> generate(int columns, int rows){
List<List<Long>> matrix = new ArrayList<>();
List<Long> row;
Random randomGenerator = new Random();
for(int i=0; i<rows; i++){
row = new ArrayList<>();
for(int j=0; j<columns; j++){
row.add((long) randomGenerator.nextInt(columns*rows+1));
}
matrix.add(row);
}
return matrix;
}
}
MultiThreadClass.java
package metodo_java8_moderno;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class MultiThreadClass {
private ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
public List<List<Long>> matrix;
public void setMatrix(List<List<Long>> matrix) {
reentrantReadWriteLock.writeLock().lock();
try {
this.matrix = matrix;
} catch (Exception e){
this.matrix = null;
} finally {
reentrantReadWriteLock.writeLock().unlock();
}
}
public List<List<Long>> getMatrix() {
reentrantReadWriteLock.readLock().lock();
List<List<Long>> matrix;
try {
matrix = this.matrix;
} catch (Exception e){
matrix = null;
} finally {
reentrantReadWriteLock.readLock().unlock();
}
return matrix;
}
public int i;
public void setI(int i) {
reentrantReadWriteLock.writeLock().lock();
try {
this.i = i;
} catch (Exception e){
this.i = -1;
} finally {
reentrantReadWriteLock.writeLock().unlock();
}
}
public int getI() {
reentrantReadWriteLock.readLock().lock();
int i;
try {
i = this.i;
} catch (Exception e){
i = -1;
} finally {
reentrantReadWriteLock.readLock().unlock();
}
return i;
}
public List<Long> numbers;
public void setNumbers(List<Long> numbers) {
reentrantReadWriteLock.writeLock().lock();
try {
this.numbers = numbers;
} catch (Exception e){
this.numbers = null;
} finally {
reentrantReadWriteLock.writeLock().unlock();
}
}
public List<Long> getNumbers() {
reentrantReadWriteLock.readLock().lock();
List<Long> numbers;
try {
numbers = this.numbers;
} catch (Exception e){
numbers = null;
} finally {
reentrantReadWriteLock.readLock().unlock();
}
return numbers;
}
public Long limit;
public void setLimit(Long limit) {
reentrantReadWriteLock.writeLock().lock();
try {
this.limit = limit;
} catch (Exception e){
this.limit = null;
} finally {
reentrantReadWriteLock.writeLock().unlock();
}
}
public Long getLimit() {
reentrantReadWriteLock.readLock().lock();
Long limit;
try {
limit = this.limit;
} catch (Exception e){
limit = null;
} finally {
reentrantReadWriteLock.readLock().unlock();
}
return limit;
}
public List<Object> editAndAdd(List<List<Long>> matrix){
this.matrix = matrix;
this.limit = (long) this.matrix.get(0).size()*this.matrix.size()/2;
this.numbers = new ArrayList<>();
int core = Runtime.getRuntime().availableProcessors();
for(int i=0; i<this.matrix.get(0).size(); i++){
this.i = i;
ForkJoinListMutator listMutator = ForkJoinListMutator.getDefault();
listMutator.mutate(this.matrix,Math.max(1,this.matrix.size()/(core*1+1)),(j) -> parallelFor(j));
}
List<Object> objectList = new ArrayList<>();
objectList.add(this.matrix);
objectList.add(this.numbers);
return objectList;
}
public void parallelFor(int j){
try{
List<List<Long>> matrix = getMatrix();
int i = getI();
List<Long> numbers = getNumbers();
Long limit = getLimit();
if(matrix.get(j).get(i).longValue() <= limit){
numbers.add(matrix.get(j).get(i));
matrix.get(j).set(i,null);
}
setMatrix(matrix);
setI(i);
setNumbers(numbers);
setLimit(limit);
//System.out.println(">> "+this.matrix);
//System.out.println(">> "+this.numbers);
}catch (Exception e){
System.out.println("Errore!");
System.out.println(e.getMessage());
System.out.println(e.getCause());
}
}
}
SingleThreadClass.java
package metodo_java8_moderno;
import java.util.ArrayList;
import java.util.List;
public class SingleThreadClass {
public List<Object> editAndAdd(List<List<Long>> matrix){
Long limit = (long) matrix.get(0).size()*matrix.size()/2;
List<Long> numbers = new ArrayList<>();
for(int i=0; i<matrix.get(0).size(); i++){
for(int j=0; j<matrix.size(); j++){
if(matrix.get(j).get(i).longValue() <= limit){
numbers.add(matrix.get(j).get(i));
matrix.get(j).set(i,null);
}
}
}
List<Object> objectList = new ArrayList<>();
objectList.add(matrix);
objectList.add(numbers);
return objectList;
}
}
i have to code the Dijkstra algorithm. We got a blueprint for this project. Meaning we were told the classes, field variables and methods we have to use.
We have to read the adjacency matrix from a csv file and then use the Dijkstra algorithm.
My problem already begins in in filling the TreeSet edges...
The problem occurs in Graph.class on line 45 when i try to add the Edges.
Example for the csv :
;A;B;C;D;E;F;G;H
A;;1;3;1;;;;
B;1;;;;3;3;;
C;3;;;1;;;1;
D;1;;1;;1;;2;
E;;3;;1;;1;;5
F;;3;;;1;;;1
G;;;1;2;;;;1
H;;;;;5;1;1;
=>
A -> (B,1), (C,3), (D,1)
B -> (A,1), (E,3), (F,3)
C -> (A,3), (D,1), (G,1)
D -> (A,1), (C,1), (E,1), (G,2)
E -> (B,3), (D,1), (F,1), (H,5)
F -> (B,3), (E,1), (H,1)
G -> (C,1), (D,2), (H,1)
H -> (E,5), (F,1), (G,1)
Could somebody look where my problem is ? My indices are correct i checked them with some sout.
Just need help with filling in the TreeSet! I want to try the Dijkstra part myself.
public class Edge implements Comparable<Edge>{
private int distance;
private Node neighbour;
public Edge(int distance, Node neighbour) {
this.distance = distance;
this.neighbour = neighbour;
}
public int getDistance() {
return distance;
}
public void setDistance(int distance) {
this.distance = distance;
}
public Node getNeighbour() {
return neighbour;
}
public void setNeighbour(Node neighbour) {
this.neighbour = neighbour;
}
#Override
public int compareTo(Edge o) {
if (this.neighbour.getId().equals(o.neighbour.getId())){
return 0;
}else{
return -1;
}
}
}
import java.util.TreeSet;
public class Node {
private String id;
private TreeSet<Edge> edges;
private int distance;
private Node previous;
private boolean isVisited;
public Node(String id) {
this.id = id;
this.edges = new TreeSet<>();
}
public Node(String id, int distance){
this.id = id;
this.distance = distance;
}
#Override
public String toString() {
return "Node{" +
"id='" + id + '\'' +
", edges=" + edges +
", distance=" + distance +
", previous=" + previous +
", isVisited=" + isVisited +
'}';
}
public String getPath(){
return null;
}
public void addEdge(Edge e){
edges.add(e);
}
public void init(){
}
public void setStartNode(Node n){
}
public void visit(Node n){
}
public String getId() {
return id;
}
}
import java.io.File;
import java.io.FileNotFoundException;
import java.nio.file.Path;
import java.util.*;
public class Graph {
private PriorityQueue pq;
private ArrayList<Node> nodes;
public Graph(){
this.pq = new PriorityQueue();
this.nodes = new ArrayList();
}
public void readGraphFromAdjacencyMatrixFile(Path file) throws FileNotFoundException {
Scanner sc = new Scanner(new File(String.valueOf(file)));
ArrayList<String> s = new ArrayList<>();
ArrayList<Character> nodesCharacter = new ArrayList<Character>();
while (sc.hasNext()){
s.add(sc.next());
}
sc.close();
for(char ch: s.get(0).toCharArray()){
if (ch != ';' && ch != ',') {
nodes.add(new Node(Character.toString(ch)));
nodesCharacter.add(ch);
}
}
ArrayList<Node> nodes2 = getNodes();
String node = "";
int index = 0;
for (int i = 1; i < s.size(); i++){
int cnt = -2;
char[] chArray = s.get(i).toCharArray();
for (int j = 0; j < chArray.length; j++){
if(j == 0){
node = String.valueOf(chArray[j]);
index = indexOfNode(String.valueOf((chArray[j])));
}
else if (j >= 2){
if (Character.isDigit(chArray[j])){
int neighbourIndex = indexOfNode("" + nodesCharacter.get(cnt));
Edge e = new Edge(Character.getNumericValue(chArray[j]), nodes.get(neighbourIndex));
nodes.get(index).addEdge(e);
cnt--;
}
}
cnt ++;
}
}
}
public String getAllPAths(){
return null;
}
public void calcWithDijkstra(String startNodeId){
}
public ArrayList<Node> getNodes() {
return nodes;
}
public int indexOfNode(String id){
int cnt = 0;
for (int i = 0; i < nodes.size(); i++){
if (id.equals(nodes.get(i).getId())){
return cnt;
}
cnt++;
}
return -1;
}
}
I have a graph that contains objects of type GraphNodes. These nodes contain an object City that has properties if It's infected or not. I want to loop through all the nodes and check if a city is infected or not. I have a generic method getInfo which returns an object of type E in my case City. But when i try to chain another method or to get property i can't see them as if they are not available. All the classes in the code are from college so i can't add/remove methods. I've tried with foreach but I still can't get the methods.
Code:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.LinkedList;
class City {
String osnovna_granka;
boolean zarazen;
City(String osnovna_granka, boolean zarazen) {
this.osnovna_granka = osnovna_granka;
this.zarazen = zarazen;
}
#Override
public String toString() {
if (zarazen == true) {
return osnovna_granka + " zarazen";
} else {
return osnovna_granka + " nezarazen";
}
}
}
class Graph {
int num_nodes;
GraphNode<City> adjList[];
#SuppressWarnings("unchecked")
public Graph(int num_nodes) {
this.num_nodes = num_nodes;
adjList = (GraphNode<City>[]) new GraphNode[num_nodes];
}
int adjacent(int x, int y) {
// proveruva dali ima vrska od jazelot so
// indeks x do jazelot so indeks y
return (adjList[x].containsNeighbor(adjList[y])) ? 1 : 0;
}
void addEdge(int x, int y) {
// dodava vrska od jazelot so indeks x do jazelot so indeks y
if (!adjList[x].containsNeighbor(adjList[y])) {
adjList[x].addNeighbor(adjList[y]);
}
}
void deleteEdge(int x, int y) {
adjList[x].removeNeighbor(adjList[y]);
}
#Override
public String toString() {
String ret = new String();
for (int i = 0; i < this.num_nodes; i++) {
ret += i + ": " + adjList[i] + "\n";
}
return ret;
}
}
class GraphNode<E> {
private int index;//index (reden broj) na temeto vo grafot
private E info;
private LinkedList<GraphNode<E>> neighbors;
public GraphNode(int index, E info) {
this.index = index;
this.info = info;
neighbors = new LinkedList<GraphNode<E>>();
}
boolean containsNeighbor(GraphNode<E> o) {
return neighbors.contains(o);
}
void addNeighbor(GraphNode<E> o) {
neighbors.add(o);
}
void removeNeighbor(GraphNode<E> o) {
if (neighbors.contains(o)) {
neighbors.remove(o);
}
}
#Override
public String toString() {
String ret = "INFO:" + info + " SOSEDI:";
for (int i = 0; i < neighbors.size(); i++) {
ret += neighbors.get(i).info + " ";
}
return ret;
}
#Override
public boolean equals(Object obj) {
#SuppressWarnings("unchecked")
GraphNode<E> pom = (GraphNode<E>) obj;
return (pom.info.equals(this.info));
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public E getInfo() {
return info;
}
public void setInfo(E info) {
this.info = info;
}
public LinkedList<GraphNode<E>> getNeighbors() {
return neighbors;
}
public void setNeighbors(LinkedList<GraphNode<E>> neighbors) {
this.neighbors = neighbors;
}
}
public class Main {
public static void main(String[] args) throws Exception {
int i, j, k;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
Graph g = new Graph(N);
for (i = 0; i < N; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
st.nextToken();
String osnovna_granka = st.nextToken();
String str_zarazen = st.nextToken();
if (str_zarazen.equals("zarazen")) {
g.adjList[i] = new GraphNode(i, new City(osnovna_granka, true));
} else {
g.adjList[i] = new GraphNode(i, new City(osnovna_granka, false));
}
}
int M = Integer.parseInt(br.readLine());
for (i = 0; i < M; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
g.addEdge(a, b);
g.addEdge(b, a);
}
br.close();
Stack<GraphNode> stack = new Stack<>();
int counter = 0;
// vasiot kod ovde;
for(GraphNode gn: g.adjList) {
gn.getInfo().// Here the properties of City should show up
}
}
}
GraphNode is a generic type and you have not specified the type, the IDE cannot infer the type so no methods can be suggested. in the for loop you need to specify the type of the GraphNode.
for(GraphNode<City> gn: g.adjList)
I have problem with this code for test this is the error error 1 error 2
and this is the code
first class
import java.util.LinkedList;
import java.util.List;
public class Position {
public char[] board;
public char turn;
public int dim =3;
private int l;
public Position() {
this.board = " ".toCharArray();
this.turn = 'x';
}
public Position(char[] board, char turn) {
this.board = board;
this.turn = turn;
}
public Position(String str) {
this.board = str.toCharArray();
this.turn = 'x';
}
public Position(String str, char turn) {
this.board = str.toCharArray();
this.turn = turn;
}
public String toString () {
return new String(board);
}
public Position move (int idx) {
char[] newBoard = board.clone();
newBoard[idx] = turn;
return new Position(newBoard, turn == 'x' ? 'o' :'x');
}
public Integer[] possibleMoves() {
List<Integer> list = new LinkedList<Integer>();
for (int i = 0; i < board.length; i++) {
if (board[i] == ' ') {
list.add(i);
}
}
Integer[] array = new Integer[list.size()];
list.toArray(array);
return array;
}
public boolean win_line(char turn, int start, int step) {
for (int i = 0; i < 3; i++) {
if (board[start + step*i] != turn) {
return false;
}
}
return true;
}
public boolean win(char turn) {
for (int i = 0; i < dim; i++) {
if (win_line(turn, i*dim, l) || win_line(turn, i,dim)) {
return true;
}
}
if (win_line(turn, dim-1, dim-1) || win_line(turn, 0, dim+1)) {
return true;
}
return false;
}
public int minimax() {
if (win('x')) { return 100; }
if (win('o')) { return -100; }
if (possibleMoves().length == 0) { return 0; }
Integer mm = null;
for (Integer idx : possibleMoves()) {
Integer value = move(idx).minimax();
if (mm == null || turn == 'x' && mm < value || turn == 'o' && value < mm) {
mm = value;
}
}
return mm + (turn == 'x' ? -1 : 1);
}
public int bestMove() {
Integer mm = null;
int best = -1;
for (Integer idx : possibleMoves()) {
Integer value = move(idx).minimax();
if (mm == null || turn == 'x' && mm < value || turn == 'o' && value < mm) {
mm = value;
best = idx;
}
}
return best;
}
public boolean gameEnd() {
return win('x') || win('o') || possibleMoves().length ==0;
}
}
Second class for test
import static org.junit.Assert.*;
import org.junit.Test;
public class PositionTest {
#Test
public void testNew() throws Exception {
Position position = new Position();
assertEquals(" ", position.toString());
assertEquals('x', position.turn);
}
#Test
public void testMove() throws Exception {
Position position = new Position().move(1);
assertEquals(" x ", position.toString());
assertEquals('o', position.turn);
}
#Test
public void testPossibleMoves() throws Exception {
Position position = new Position().move(1).move(3).move(4);
assertArrayEquals(new Integer[] {0,2,5,6,7,8}, position.possibleMoves());
}
#Test
public void testWin() throws Exception {
assertFalse(new Position().win('x'));
assertTrue(new Position("xxx ").win('x'));
assertTrue(new Position(" ooo ").win('o'));
assertTrue(new Position("x x x ").win('x'));
assertTrue(new Position(" x x x ").win('x'));
assertTrue(new Position("x x x").win('x'));
}
#Test
public void testMinimax() throws Exception {
assertEquals( 100, new Position("xxx ").minimax());
assertEquals(-100, new Position("ooo ").minimax());
assertEquals( 0, new Position("xoxoxooxo").minimax());
assertEquals( 99, new Position(" xx ").minimax());
assertEquals( -99, new Position(" oo ", 'o').minimax());
}
#Test
public void testBestMove() throws Exception {
assertEquals(0, new Position(" xx ").bestMove());
assertEquals(1, new Position("o o ", 'o').bestMove());
}
#Test
public void testGameEnd() throws Exception {
assertFalse(new Position().gameEnd());
assertTrue(new Position("xxx ").gameEnd());
}
}
third class
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
public class Game {
Position position;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("Java TTT");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridLayout(3, 3));
final Game game = new Game();
final JButton[] buttons = new JButton[9];
for (int i =0; i < 9; i++) {
final int idx = i;
final JButton button = new JButton();
buttons[i] = button;
button.setPreferredSize(new Dimension(100,100));
button.setBackground(Color.BLACK);
button.setOpaque(true);
button.setFont(new Font(null, Font.PLAIN, 100));
button.addMouseListener(new MouseListener() {
public void mouseReleased(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
#Override
public void mouseClicked(MouseEvent e) {
button.setText("" + game.position.turn);
game.move(idx);
if (!game.position.gameEnd()){
int best = game.position.bestMove();
buttons[best].setText("" + game.position.turn);
game.move(best);
}
if (game.position.gameEnd()) {
String message = "";
if (game.position.win('x')) {
message = "You Won !!";
} else if (game.position.win('o')){
message = "Computer Won !!";
} else {
message = "Draw";
}
JOptionPane.showMessageDialog(null, message);
}
}});
frame.add(button);
}
frame.pack();
frame.setVisible(true);
}
});
}
protected void move(int idx) {
position = position.move(idx);
}
}
1- java.lang.AssertionError: array lengths differed, expected.length=6
actual.length=5
2-java.lang.AssertionError: expected:<0> but was:<100>
assertionsErrors within unit testcase runs are telling you that the actual result does not fit the expected one. thus your code does not work properly and you have to fix this.
please post the lines where these errors occurr.
Im pretty new to Java and to thread-programming especially. This code is mostly out of a pretty old book (2001) with samples and examples for a search-engine.
But its just not working
Now i don't know if i am making a mistake or if the author made it or if there are incompatibilities with different versions of java...i really have no clue! The oddest thing about it is that it works 1 out of 100 times ...
After hours of debugging i would appreciate any help!
SearchEngine.java:
import java.util.Vector;
import parsing.SourceElement;
import parsing.WebParserWrapper;
import query.Filter;
public class SearchEngine implements Runnable {
private Vector linkHistory = new Vector();
private int currentLink;
private String beginAt = null;
private SearchHandler searchHandler = null;
private boolean searchInProgress = false;
private boolean stopPending = false;
boolean firstTime = true;
public boolean searchInProgress() {
return searchInProgress;
}
public boolean stopPending() {
return stopPending;
}
#SuppressWarnings("unchecked")
public void followLinks(String url) {
if (stopPending)
return;
try {
boolean drillDown = false;
WebParserWrapper webParser = new WebParserWrapper();
Vector sortedElements = webParser.getElements(url, "", "WITHGET");
Vector contentElements = Filter.getFilteredElements(sortedElements, Filter.CONTENT, "matches", "*");
for (int i = 0; i < contentElements.size(); i++) {
SourceElement thisElement = (SourceElement) contentElements.elementAt(i);
String thisKey = (String) thisElement.getKey();
String thisContent = (String) thisElement.getContent();
boolean goodHit = searchHandler.handleElement(url, thisKey, thisContent);
if (goodHit) {
drillDown = true;
}
}
System.out.println(url + " -- DrillDown " + ((drillDown) ? "positive" : "negative"));
if (drillDown) {
Vector linkElements = Filter.getFilteredElements(sortedElements, Filter.KEY, "matches",
"*a[*].#href[*]");
for (int i = 0; i < linkElements.size(); i++) {
SourceElement thisElement = (SourceElement) linkElements.elementAt(i);
String thisContent = (String) thisElement.getContent();
if (!linkHistory.contains(thisContent)) {
linkHistory.add(thisContent);
System.out.println("Collected: " + thisContent);
}
}
}
}
catch (Exception e) {}
if (currentLink < linkHistory.size()) {
String nextLink = (String) linkHistory.elementAt(currentLink++);
if (nextLink != null) {
followLinks(nextLink);
}
}
}
public boolean startSearch(String url, SearchHandler searchHandler) {
if (searchInProgress)
return false;
beginAt = url;
this.searchHandler = searchHandler;
this.linkHistory = new Vector();
this.currentLink = 0;
Thread searchThread = new Thread(this);
searchThread.start();
return true;
}
public void stopSearch() {
stopPending = true;
}
#Override
public void run() {
searchInProgress = true;
followLinks(beginAt);
searchInProgress = false;
stopPending = false;
}
}
SimpleSearcher.java
import java.util.Enumeration;
import java.util.Hashtable;
public class SimpleSearcher implements SearchHandler {
private SearchEngine searchEngine;
private String keyword;
private String startURL;
private Hashtable hits = new Hashtable();
public boolean handleElement(String url, String key, String content) {
boolean goodHit = false;
int keywordCount = 0;
int pos = -1;
while ((pos = content.toLowerCase().indexOf(keyword, pos + 1)) >= 0){
keywordCount++;
}
if (keywordCount > 0) {
Integer count = (Integer) hits.get(url);
if (count == null){
hits.put(url, new Integer(1));
}
else {
hits.remove(url);
hits.put(url, new Integer(count.intValue() + keywordCount));
}
goodHit = true;
}
if (hits.size() >= 3)
searchEngine.stopSearch();
return goodHit;
}
public Hashtable search(String startURL, String keyword) {
searchEngine = new SearchEngine();
this.startURL = startURL;
this.keyword = keyword;
searchEngine.startSearch(startURL, this);
try {Thread.sleep(1000);}catch (Exception e){e.printStackTrace();}
while (searchEngine.searchInProgress());
return this.hits;
}
public static void main(String[] args) {
SimpleSearcher searcher = new SimpleSearcher();
String url = "http://www.nzz.ch/";
String compareWord = "der";
Hashtable hits = searcher.search(url, compareWord);
System.out.println("URLs=" + hits.size());
for (Enumeration keys = hits.keys(); keys.hasMoreElements();) {
String thisKey = (String) keys.nextElement();
int thisCount = ((Integer) hits.get(thisKey)).intValue();
System.out.println(thisCount + " hits at " + thisKey);
}
}
}
SearchHandler.java
public interface SearchHandler {
public boolean handleElement(String url, String key, String content);
}