java - Error casting Set.toArray() as Object[] - java

I am attempting to grab a random element from a Set of custom Objects (Space) and receiving an error in doing so.
Space[][][][] spaces = new Space[dim][dim][dim][dim];
Set<Space> spaceSet = new HashSet<Space>();
for(int i=0; i<dim; i++)
for(int j=0; j<dim; j++)
for(int k=0; k<dim; k++)
for(int l=0; l<dim; l++) {
spaces[i][j][k][l] = new Space(i,j,k,l);
spaceSet.add(spaces[i][j][k][l]);
}
...
Space s = null;
...
s = (Space[])spaceSet.toArray()[rand.nextInt(spaceSet.size())]; //This line throws the error
Error:
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [LSpace;
at Maze.generatePath(Maze.java:45)
at Maze4D.main(Maze4D.java:15)

An array of Objects cannot be cast to an array of Foos. You will need to iterate over the array and cast each member individually. (Better yet, properly use generics / polymorphism and don't cast.)

Because as the docs point out, toArray() returns an Object[]
You need to use the other toArray(T[] a) if you want the type inferred:
s = spaceSet.toArray(new Space[0])[rand.nextInt(spaceSet.size())];
(The supplied array in this case is just being used for the type inference; toArray() is returning a new Space[] of the appropriate size)

When trying to work with Random size/space. Its always a better idea to use a map instead of arrays going down several levels. Here is an example of the something similar where you could set/get values with minimal boiler plate code.
import java.util.*;
public class SmartPropertyReader {
private SmartPropertyReader parent;
protected final String PRESERVE_MAP = "PRESERVE_MAP";
protected final String PRESERVE_LIST = "PRESERVE_LIST";
private String preserveType;
protected Map<String, SmartPropertyReader> map = new HashMap<String, SmartPropertyReader>();
protected Object value;
protected List<SmartPropertyReader> list = new ArrayList<SmartPropertyReader>();
public SmartPropertyReader(){
this.parent = null;
}
public SmartPropertyReader(SmartPropertyReader parent, String preserveType) {
this.parent = parent;
this.preserveType = preserveType;
}
public SmartPropertyReader get(String key) {
SmartPropertyReader subProp = map.get(key);
if(subProp == null){
subProp = new SmartPropertyReader(this, PRESERVE_MAP);
map.put(key, subProp) ;
}
return subProp;
}
public void setValue(Object passedValue) {
list.clear();
map.clear();
if(passedValue instanceof SmartPropertyReader){
this.map = ((SmartPropertyReader) passedValue).map;
this.list = ((SmartPropertyReader) passedValue).list;
}else{
this.value = passedValue;
}
SmartPropertyReader currPropertyReader = this;
while(currPropertyReader != null){
String preserveType = currPropertyReader.preserveType;
currPropertyReader = currPropertyReader.parent;
if(PRESERVE_MAP.equals(preserveType)){
currPropertyReader.clearList();
currPropertyReader.clearValue();
}else if(PRESERVE_LIST.equals(preserveType)){
currPropertyReader.clearValue();
currPropertyReader.clearMap();
}
}
}
protected void clearList(){
list.clear();
}
protected void clearMap(){
map.clear();
}
protected void clearValue(){
this.value = null;
}
public Object getValue() {
if(this.value == null){
SmartPropertyReader currPropertyReader = parent;
while(currPropertyReader != null){
String preserveType = currPropertyReader.preserveType;
if(PRESERVE_MAP.equals(preserveType)){
currPropertyReader.clearMap();
}else if(PRESERVE_LIST.equals(preserveType)){
currPropertyReader.clearList();
}
currPropertyReader = currPropertyReader.parent;
}
}
return this.value;
}
public SmartPropertyReader get(int index) {
while(list.size() <= index ){
list.add(null);
}
SmartPropertyReader subProp = list.get(index);
if(subProp == null){
subProp = new SmartPropertyReader(this, PRESERVE_LIST);
}
list.set(index, subProp);
return subProp;
}
public String toString(){
String retString = "";
if(value != null){
retString = value.toString();
if(value instanceof String){
retString = "\"" + retString + "\"";
}
}
if(list.size() > 0){
String listStr = listString();
if(!listStr.equals(""))
retString = "[" + listString() + "]";
}
if(map.size() > 0){
String mapStr = mapString();
if(!mapStr.equals(""))
retString = "{" +mapString() + "}";
}
return retString;
}
private String listString (){
String str = "";
boolean first = true;
for(SmartPropertyReader rblt: list){
if(rblt != null ){
String subStr = rblt.toString();
if(!subStr.equals("")){
if(!first)
str += ", ";
str += subStr;
first = false;
}
}
}
return str;
}
private String mapString(){
String str ="";
boolean first = true;
for(String key: map.keySet()){
SmartPropertyReader rblt = map.get(key);
if(rblt != null){
String subStr = rblt.toString();
if(!subStr.equals("")){
if(!first)
str += ", ";
str += "\""+key + "\": " + subStr;
first = false;
}
}
}
return str;
}
public static void main(String[] args) {
SmartPropertyReader propertyReader = new SmartPropertyReader();
propertyReader.get("Test").get("2nd key").get("A number value").setValue(10);
propertyReader.get("Test").get("a key").get(1).get(2).setValue(100);
propertyReader.get("Test").get("a key").get(1).get(3).setValue(100.345);
propertyReader.get("Test").get("a key").get(2).get("Nice").setValue("Nice value in the stack");
propertyReader.get("Test").get("a key").get(5).setValue("This would work too");
System.out.println(propertyReader.toString());
System.out.println(propertyReader.get("Test").get("2nd key").get("A number value").getValue());
System.out.println(propertyReader.get("Test").get("a key").get(1).get(2).getValue());
System.out.println(propertyReader.get("Test").get("a key").get(1).get(3).getValue());
System.out.println(propertyReader.get("Test").get("a key").get(2).get("Nice").getValue());
System.out.println(propertyReader.get("Test").get("a key").get(5).getValue());
}
}

Related

why my program don't recognize the .txt file

I try to made a program which print the top 20 frequently words in a text file in java, and i have 3 classes but i don't know why can not compile it help me please. I show you the tree classes just to have an idea:
1)
public class Client {
public static void main(String[] args) {
Map<String, Integer> frequencies = new TreeMap<String, Integer>();
while(file.hasNext()){//Este lazo lee las palabras y crea el TreeMap
String word= clean(doc.next());
Integer count = frequencies.get(word);
if(count==null){
count = 1;}
else {
count = count + 1;
}
}
Object[] Claves = frequencies.keySet().toArray();
Object[] Valores = frequencies.values().toArray();
Par[] par = new Par[frequencies.size()];
for (int i=0;i<frequencies.size();i++){
Par p = new Par(Claves[i].toString(),(int) Valores[i]);
par[i]=p;
}
Arrays.sort(par);
showResult(par);
}
public static void showResult(Par[] arreglo){
System.out.println("The 20 most frequently words are ");
for(int i= 0; i<=19; i++){
System.out.print("Word "+ arreglo[i].Clave + " in " + arreglo[i].Valor + " times.");
}
}
}
2)
public class Par implements Comparable {
String Clave;
int Valor;
public int length;
public Par(String clave, int valor){
this.Clave = clave;
this.Valor = valor;
}
public int compareTo(Par p) {
if(this.Valor<p.Valor){
return 1;
}
else if(this.Valor==p.Valor){
return 0;
}
else{
return -1;
}
}
}
3)
public class ProcessText {
public void reader(Path r){
String name = clean(file.getName());
if(file.getName().equals(name + ".txt" || file.getName().equals(name + ".doc" ))){
try (Scanner sc = new Scanner(r)){
String doc = "";
while(sc.hasNextLine()){
String linea = (sc.nextLine());
doc = doc.concat(linea + "\n");
}
sc.close();
}
}
}
public static String clean(String s){
String r = "";
for (int i=0;i<s.length();i++){
char c = s.charAt(i);
if (Character.isLetter(c)){
r = r + c;
}
}
return r.toLowerCase();
}
}
If this is all the code you have, your problem might be that your main method never creates a variable called "doc" or "file", but you use them both at the beginning of Client's main method.
It would be more helpful if you could share the compile time error, though, so I can't be sure that this is your problem.

How can I improve the efficiency and/or performance of my relatively simple Java counting method?

I'm building a classifier which has to read through a lot of textdocuments, but I found out that my countWordFrequenties method gets slower the more documents it has processed. This method underneath takes 60ms (on my PC), while reading, normalizing, tokenizing, updating my vocabulary and equalizing of different lists of integers only takes 3-5ms in total (on my PC). My countWordFrequencies method is as follows:
public List<Integer> countWordFrequencies(String[] tokens)
{
List<Integer> wordFreqs = new ArrayList<>(vocabulary.size());
int counter = 0;
for (int i = 0; i < vocabulary.size(); i++)
{
for (int j = 0; j < tokens.length; j++)
if (tokens[j].equals(vocabulary.get(i)))
counter++;
wordFreqs.add(i, counter);
counter = 0;
}
return wordFreqs;
}
What is the best way for me to speed this process up? What is the problem of this method?
This is my entire Class, there is another Class Category, is it a good idea to post this also here or don't you guys need it?
public class BayesianClassifier
{
private Map<String,Integer> vocabularyWordFrequencies;
private List<String> vocabulary;
private List<Category> categories;
private List<Integer> wordFrequencies;
private int trainTextAmount;
private int testTextAmount;
private GUI gui;
public BayesianClassifier()
{
this.vocabulary = new ArrayList<>();
this.categories = new ArrayList<>();
this.wordFrequencies = new ArrayList<>();
this.trainTextAmount = 0;
this.gui = new GUI(this);
this.testTextAmount = 0;
}
public List<Category> getCategories()
{
return categories;
}
public List<String> getVocabulary()
{
return this.vocabulary;
}
public List<Integer> getWordFrequencies()
{
return wordFrequencies;
}
public int getTextAmount()
{
return testTextAmount + trainTextAmount;
}
public void updateWordFrequency(int index, Integer frequency)
{
equalizeIntList(wordFrequencies);
this.wordFrequencies.set(index, wordFrequencies.get(index) + frequency);
}
public String readText(String path)
{
BufferedReader br;
String result = "";
try
{
br = new BufferedReader(new FileReader(path));
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null)
{
sb.append(line);
sb.append("\n");
line = br.readLine();
}
result = sb.toString();
br.close();
}
catch (IOException e)
{
e.printStackTrace();
}
return result;
}
public String normalizeText(String text)
{
String fstNormalized = Normalizer.normalize(text, Normalizer.Form.NFD);
fstNormalized = fstNormalized.replaceAll("[^\\p{ASCII}]","");
fstNormalized = fstNormalized.toLowerCase();
fstNormalized = fstNormalized.replace("\n","");
fstNormalized = fstNormalized.replaceAll("[0-9]","");
fstNormalized = fstNormalized.replaceAll("[/()!?;:,.%-]","");
fstNormalized = fstNormalized.trim().replaceAll(" +", " ");
return fstNormalized;
}
public String[] handleText(String path)
{
String text = readText(path);
String normalizedText = normalizeText(text);
return tokenizeText(normalizedText);
}
public void createCategory(String name, BayesianClassifier bc)
{
Category newCategory = new Category(name, bc);
categories.add(newCategory);
}
public List<String> updateVocabulary(String[] tokens)
{
for (int i = 0; i < tokens.length; i++)
if (!vocabulary.contains(tokens[i]))
vocabulary.add(tokens[i]);
return vocabulary;
}
public List<Integer> countWordFrequencies(String[] tokens)
{
List<Integer> wordFreqs = new ArrayList<>(vocabulary.size());
int counter = 0;
for (int i = 0; i < vocabulary.size(); i++)
{
for (int j = 0; j < tokens.length; j++)
if (tokens[j].equals(vocabulary.get(i)))
counter++;
wordFreqs.add(i, counter);
counter = 0;
}
return wordFreqs;
}
public String[] tokenizeText(String normalizedText)
{
return normalizedText.split(" ");
}
public void handleTrainDirectory(String folderPath, Category category)
{
File folder = new File(folderPath);
File[] listOfFiles = folder.listFiles();
if (listOfFiles != null)
{
for (File file : listOfFiles)
{
if (file.isFile())
{
handleTrainText(file.getPath(), category);
}
}
}
else
{
System.out.println("There are no files in the given folder" + " " + folderPath.toString());
}
}
public void handleTrainText(String path, Category category)
{
long startTime = System.currentTimeMillis();
trainTextAmount++;
String[] text = handleText(path);
updateVocabulary(text);
equalizeAllLists();
List<Integer> wordFrequencies = countWordFrequencies(text);
long finishTime = System.currentTimeMillis();
System.out.println("That took 1: " + (finishTime-startTime)+ " ms");
long startTime2 = System.currentTimeMillis();
category.update(wordFrequencies);
updatePriors();
long finishTime2 = System.currentTimeMillis();
System.out.println("That took 2: " + (finishTime2-startTime2)+ " ms");
}
public void handleTestText(String path)
{
testTextAmount++;
String[] text = handleText(path);
List<Integer> wordFrequencies = countWordFrequencies(text);
Category category = guessCategory(wordFrequencies);
boolean correct = gui.askFeedback(path, category);
if (correct)
{
category.update(wordFrequencies);
updatePriors();
System.out.println("Kijk eens aan! De tekst is succesvol verwerkt.");
}
else
{
Category correctCategory = gui.askCategory();
correctCategory.update(wordFrequencies);
updatePriors();
System.out.println("Kijk eens aan! De tekst is succesvol verwerkt.");
}
}
public void updatePriors()
{
for (Category category : categories)
{
category.updatePrior();
}
}
public Category guessCategory(List<Integer> wordFrequencies)
{
List<Double> chances = new ArrayList<>();
for (int i = 0; i < categories.size(); i++)
{
double chance = categories.get(i).getPrior();
System.out.println("The prior is:" + chance);
for(int j = 0; j < wordFrequencies.size(); j++)
{
chance = chance * categories.get(i).getWordProbabilities().get(j);
}
chances.add(chance);
}
double max = getMaxValue(chances);
int index = chances.indexOf(max);
System.out.println(max);
System.out.println(index);
return categories.get(index);
}
public double getMaxValue(List<Double> values)
{
Double max = 0.0;
for (Double dubbel : values)
{
if(dubbel > max)
{
max = dubbel;
}
}
return max;
}
public void equalizeAllLists()
{
for(Category category : categories)
{
if (category.getWordFrequencies().size() < vocabulary.size())
{
category.setWordFrequencies(equalizeIntList(category.getWordFrequencies()));
}
}
for(Category category : categories)
{
if (category.getWordProbabilities().size() < vocabulary.size())
{
category.setWordProbabilities(equalizeDoubleList(category.getWordProbabilities()));
}
}
}
public List<Integer> equalizeIntList(List<Integer> list)
{
while (list.size() < vocabulary.size())
{
list.add(0);
}
return list;
}
public List<Double> equalizeDoubleList(List<Double> list)
{
while (list.size() < vocabulary.size())
{
list.add(0.0);
}
return list;
}
public void selectFeatures()
{
for(int i = 0; i < wordFrequencies.size(); i++)
{
if(wordFrequencies.get(i) < 2)
{
vocabulary.remove(i);
wordFrequencies.remove(i);
for(Category category : categories)
{
category.removeFrequency(i);
}
}
}
}
}
Your method has O(n*m) run time ( n being the vocabulary size and m the token size). With hashing this could be reduced to O(m) which is clearly better.
for (String token: tokens) {
if(!map.containsKey(token)){
map.put(token,0);
}
map.put(token,map.get(token)+1);
}
Using a Map should dramatically increase performance, as Sleiman Jneidi suggested in his answer. This can be done, however, much more elegantly with Java 8's streaming APIs:
Map<String, Long> frequencies =
Arrays.stream(tokens)
.collect(Collectors.groupingBy(Function.identity(),
Collectors.counting()));
Instead of using a list for the vocabulary, and another one for the frequencies, I'd use a Map that will store word->frequency. That way you can avoid the double loop which in my mind is what kills your performance.
public Map<String,Integer> countWordFrequencies(String[] tokens) {
// vocabulary is Map<String,Integer> initialized with all words as keys and 0 as value
for (String word: tokens)
if (vocabulary.containsKey(word)) {
vocabulary.put(word, vocabulary.get(word)+1);
}
return vocabulary;
}
If you don't want to use Java 8 stuff you can try to use MultiSet from guava

Creating node with weight in java graph

I am creating a program to create a graph for bibliography dataset. The graph is directed, has Author node and Paper node, and has 2 types of edges (author to paper edge, paper to paper edge).
I want to get an input from you about whether or not what I am creating is making sense. Right now, it produces the right result when I want to get the outEdge and inEdge from and to a node. But im not sure if this implementation is correct in terms of the methods, designs, and algorithm.
Also, I have a problem with assigning weight to a node. I want to ask how can I do this as well. Right now, what I have tried is as follows:
for (String item : CandidateAuthorType1Unique) {
double weight = Collections.frequency(CandidateAuthorType1, item);
n.setWeight(item,weight);;
System.out.println(n.getName() + " : " + n.getWeight());
}
However, after using setWeight, the getName() method returns null. This means that the weight assigned is not assigned to a certain item. I wonder how to update the weight a certain item.
If I use
for (String item : CandidateAuthorType1Unique) {
double weight = Collections.frequency(CandidateAuthorType1, item);
n = new Node(item,weight);
System.out.println(n.getName() + " : " + n.getWeight());
}
Does it mean that each time a new node n is created, the old n node will not be stored? How can I checked every node ever created and its weight?
I would like to ask for your input to this program. Any input would be really helpful for me. Thank you.
Main class: Ranker.java
import java.util.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.sql.*;
public class Ranker {
static Graph g;
static Node n;
static Edge e;
static HashMap nodeMap; // maps Integer NodeIDs to Node object
String id;
double weight;
Ranker() {
g = new Graph();
nodeMap = new HashMap();
n = new Node(id,weight);
}
public static void main (String[] args) throws ClassNotFoundException, SQLException, IOException, IllegalArgumentException, IllegalAccessException{
Ranker Ranker = new Ranker();
Connection connect = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
HashMap nodeMap = new HashMap(); // maps Integer NodeIDs to Node objects
Class.forName("com.mysql.jdbc.Driver");
connect = DriverManager.getConnection("jdbc:mysql://localhost/arnetminer?"+"user=root&password=1234");
preparedStatement = connect.prepareStatement("Select fr,t,ty from subedge");
resultSet = preparedStatement.executeQuery();
int i=0;
while(resultSet.next()) {
g.addEdgeForIndexing(resultSet.getInt(1),resultSet.getInt(2),resultSet.getInt(3));
i++;
System.out.println( "edges added to G = "+i);
}
System.out.println("Loaded " + g.nodeCount() + " nodes.");
buildNodes();
System.out.println("Enter first author key:");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String authorkey1 = br.readLine();
int authorID1 = Integer.parseInt(authorkey1);
String AuthorID1 = "A"+authorID1;
ArrayList<String> p1 = g.getOutEdgesToP(AuthorID1);
System.out.println("P1 = " + p1);
ArrayList<String> p2 = new ArrayList<String>();
for (int j = 0; j<p1.size();j++){
ArrayList<String> temp = g.getOutEdgesToP(p1.get(j));
if (temp!=null)
p2.addAll(temp);
}
System.out.println("P2 = " +p2);
ArrayList<String> CandidateAuthorType1 = new ArrayList<String>();
for (int k = 0; k<p2.size(); k++){
ArrayList<String> temp = g.getInEdgesFromPtoA(p2.get(k));
if(temp!=null)
CandidateAuthorType1.addAll(temp);
}
System.out.println("Candidate Author Type 1= " + CandidateAuthorType1);
ArrayList<String> CandidateAuthorType1Unique = removeDuplicates(CandidateAuthorType1);
System.out.println("-----------------------------------------------");
System.out.println("Candidate author type 1 and author node weight:");
for (String item : CandidateAuthorType1Unique) {
double weight = Collections.frequency(CandidateAuthorType1, item);
n.setWeight(item,weight);;
System.out.println(n.getName() + " : " + n.getWeight());
}
ArrayList<String> CandidatePaperType1 = new ArrayList<String>();
for (int l = 0; l<CandidateAuthorType1.size(); l++){
ArrayList<String> temp = g.getOutEdgesToP(CandidateAuthorType1.get(l));
if(temp!=null)
CandidatePaperType1.addAll(temp);
}
System.out.println("Candidate Paper Type 1= " + CandidatePaperType1);
}
private static ArrayList<String> removeDuplicates(ArrayList<String> element){
ArrayList<String> result = new ArrayList<>();
HashSet<String> set = new HashSet<>();
for (String item : element) {
if (!set.contains(item)) {
result.add(item);
set.add(item);
}
}
return result;
}
private static void buildNodes()
{
String nodeID;
double weight = 0;
Node n;
Iterator it = g.nodeIteratorInitial();
while (it.hasNext()) {
nodeID = (String) it.next();
if (!nodeMap.containsKey(nodeID)){
n = new Node(nodeID,weight);
nodeMap.put(nodeID, 0);
}
}
}
}
Graph.java
import java.lang.reflect.Field;
import java.util.*;
public class Graph {
private HashSet<String> nodeIDs;
public HashMap<Integer, String> nodeIDsWithTN;
public HashMap<Integer, String> TNMap;
private HashMap<String, ArrayList<String>> edges;
private HashMap<String, ArrayList<String>> reverse;
private int numNodes;
private int numEdges;
private int numReverse;
public Graph() {
edges = new HashMap<String, ArrayList<String>>();
reverse = new HashMap<String, ArrayList<String>>();
nodeIDs = new HashSet<String>();
nodeIDsWithTN = new HashMap<Integer, String>();
TNMap = new HashMap<Integer, String>();
new HashSet();
}
public void addEdgeForIndexing(int from, int to, int T) throws IllegalArgumentException, IllegalAccessException {
String From = ""+from;
String To = ""+to;
int type = T;
if(T==1)
{
From="A"+from;
To="P"+to;
}
else if(T==2)
{
From="P"+from;
To="P"+to;
}
else
System.out.println("T ="+T+" value undefined");
Edge e = new Edge(From,To,type);
nodeIDs.add(e.From);
nodeIDs.add(e.To);
ArrayList<String> tmp = null;
if (edges.containsKey(e.From))
tmp = (ArrayList<String>) edges.get(e.From);
else {
tmp = new ArrayList<String>();
edges.put(e.From,tmp);
}
tmp.add(e.To);
ArrayList<String> tmp2 = null;
if (reverse.containsKey(e.To))
tmp2 = (ArrayList<String>) reverse.get(e.To);
else {
tmp2 = new ArrayList<String>();
reverse.put(e.To,tmp2);
}
tmp2.add(e.From);
}
public int nodeCount() {
if(nodeIDs.size() > 0)
return nodeIDs.size();
// else return numNodes;
return numEdges;
}
public int countInEdges(Integer key) {
if (!reverse.containsKey(key)) return 0;
return ((ArrayList<?>) reverse.get(key)).size();
}
public int countOutEdges(Integer key) {
if (!edges.containsKey(key)) return 0;
return ((ArrayList<?>) edges.get(key)).size();
}
public ArrayList<String> getInEdgesFromPtoA(String id) {
if (!reverse.containsKey(id)) return null;
ArrayList<String> a = reverse.get(id);
ArrayList<String> result = new ArrayList<String>();
for(int j=0;j<a.size();j++){
if(a.get(j).startsWith("A")){
result.add(a.get(j));
}
}
return result;
}
public ArrayList<String> getOutEdgesToP(String id) {
if (!edges.containsKey(id)) return null;
ArrayList<String> a = edges.get(id);
ArrayList<String> result = new ArrayList<String>();
for(int j=0;j<a.size();j++){
if(a.get(j).startsWith("P")){
result.add(a.get(j));
}
}
return result;
}
public Iterator<String> nodeIteratorInitial() {
return nodeIDs.iterator();
}
}
Edge.java
public class Edge {
String From;
String To;
int type;
private static int counter = 0;
public Edge(String From, String To, int type) {
this.From = new String(From);
this.To = new String(To);
this.type = type;
// System.out.println("edges added from " + From + " to " + To + " with type "+ type);
}
public String getFrom(){
return From;
}
public String getTo(){
return To;
}
public int getType(){
return type;
}
public void setFrom(String From){
this.From = From;
}
public void setTo(String To){
this.To = To;
}
public void setType(int type){
this.type = type;
}
}
Node.java
public class Node {
String id;
double weight;
private static int counter = 0;
public Node(String id,double weight) {
this.id = id;
this.weight = weight;;
}
public double getWeight(){
return weight;
}
public String getName() {
return id;
}
public void setWeight(String id, double weight){
if (this.id==id){
this.weight=weight;}
System.out.println("The node " + id + " has weight " + weight);
}
public void setName(String id){
this.id=id;
}
}
As you are initialising n in the Ranker() constructor, when the constructor is called, the String id has not been assigned and therefore always contains the value null. Therefore your Node n also gets the id as null. This is the reason why the weight isn't updated as in your setWeight(String id, double weight) function, the new id is compared to null which always returns false therefore the weight doesn't get updated.
You could make the following changes in your code
1) Remove the n = new Node(id,weight) initialisation in your Ranker() constructor.
2) Add the following lines instead of n.setWeight(item,weight) in your main method in Ranker class.
if (n == null)
n = new Node(item, weight);
n.setWeight(item, weight);

ArrayList<superclass> but use ArrayList<subclass>.methodofsubclass

Im having a class Woning (house) and a subclass KoopWoning (buyable House) and a subclass HuurWoning (rentable House). KoopWoning and Huurwoning extend Woning. HuurWoning is just a Woning, whereas KoopWoning has an extra variable energylevel. KoopWoning has also a function getEnergylevel, which returns the energylevel of the KoopWoning. I also have a class Portefeuille which has an arraylist of Woningen.
Im reading all Woningen in a Portefeuille from a textfile. In a 5th class, I want to be able to sort the ArrayList of Woningen of Portefeuille (from the textfile). I have a function woningenTot(int maxprijs) which returns an ArrayList with all the Woningen that fullfil the requirement (having a price below maxprijs). These Woningen I want to print on the screen.
The problem is as follows:
It can be possible that there is also a KoopWoning in the file. In that case I also want to be able to sort on energylevel. However, I can't sort on the energylevels. I can't call the function getEnergylevel because it's an ArrayList, and Woning doesn't contain the function getEnergylevel.
So how can I solve this? If it's too vague, I could include the code, however it's quite big :O
Any help is appreciated; i have spent a couple of hours on this program, from which at least 1.5 hours on this problem alone :(
EDIT: Here is the code for class KoopWoning
public class KoopWoning extends Woning implements EnergiepeilWoning {
private char energiepeil;
public KoopWoning (Adres adres, int kamers, int vraagPrijs, char energiepeil) {
super(adres, kamers, vraagPrijs);
this.energiepeil = energiepeil;
}
public char getEnergiepeil () {
return energiepeil;
}
public boolean compareEnergiepeil (Object other) {
boolean res = false;
if (other instanceof KoopWoning) {
KoopWoning that = (KoopWoning) other;
res = (this.getEnergiepeil() == that.getEnergiepeil());
}
return res;
}
public String toString () {
String res = adres + ", " + kamers + " kamers, prijs " + prijs + ", energiepeil " + energiepeil;
return res;
}
And here is the code for class Woning
public class Woning {
protected int kamers;
protected int prijs;
protected Adres adres;
protected String tag;
public Woning (Adres adres, int kamers, int prijs) {
this.adres = adres;
this.kamers = kamers;
this.prijs = prijs;
}
public String toString () {
String res = adres + ", " + kamers + " kamers, prijs " + prijs;
return res;
}
public void setTag (String tag) {
this.tag = tag;
}
public String getTag () {
return tag;
}
public boolean kostHooguit (int maxprijs) {
return (prijs <= maxprijs);
}
public boolean equals (Object other) {
boolean res = false;
if (other instanceof Woning) {
Woning that = (Woning) other;
if (this.adres.equals(that.adres))
res = true;
}
return res;
}
public static Woning read (Scanner sc) {
try {
Adres adress = Adres.read(sc);
int kamer = sc.nextInt();
sc.next();
sc.next();
int prijs = sc.nextInt();
String check = sc.next();
if (check.equals("energiepeil")) {
char peil = sc.next().charAt(0);
KoopWoning kwoning = new KoopWoning (adress, kamer, prijs, peil);
return kwoning;
}
else {
Woning woning = new Woning (adress, kamer, prijs);
return woning;
}
}
catch (Exception e) {
System.out.println("Woning: Exception is caught");
System.out.println(e.getMessage());
Adres adress = new Adres ("", "", "", "");
Woning woning = new Woning (adress, 0, 0);
return woning;
}
}
}
And lastly, the code for the class Portefeuille
public class Portefeuille {
private ArrayList<Woning> woninglijst;
public Portefeuille () {
woninglijst = new ArrayList<Woning>();
}
public void voegToe (Woning woning) {
if (!woninglijst.contains(woning))
woninglijst.add(woning);
}
public ArrayList<Woning> woningenTot (int maxprijs) {
ArrayList<Woning> woninglijst2 = new ArrayList<Woning>();
for (int i = 0; i < woninglijst.size(); i++) {
if(woninglijst.get(i).kostHooguit(maxprijs))
woninglijst2.add(woninglijst.get(i));
}
return woninglijst2;
}
public String toStringExt () {
String res = "[";
for (int i = 0; i < woninglijst.size(); i++)
res = res + woninglijst.get(i).toString() + "; ";
if (woninglijst.size() != 0)
res = res.substring (0, res.length() - 2);
res = res + "]";
return res;
}
public String toString () {
String res = "";
for (int i = 0; i < woninglijst.size(); i++)
res = woninglijst.get(i).toString2();
return res;
}
public boolean equals (Object other) {
boolean res = false;
if (other instanceof Portefeuille) {
Portefeuille that = (Portefeuille) other;
if (this.woninglijst.size() == that.woninglijst.size()) {
int i = 0;
while (i < this.woninglijst.size() && this.woninglijst.get(i).equals(that.woninglijst.get(i)))
i = i + 1;
res = (i == this.woninglijst.size());
}
}
return res;
}
public static Portefeuille read (String infile) {
try {
Scanner sc = new Scanner (new File(infile));
ArrayList<Woning> wlijst = new ArrayList<Woning>();
Portefeuille p = new Portefeuille();
int woningen = sc.nextInt();
int i = 0;
while (i < woningen) {
sc.nextLine();
String tag = sc.nextLine();
wlijst.add(Woning.read(sc));
p.voegToe(wlijst.get(i));
i++;
}
sc.close();
return p;
}
catch (Exception e) {
System.out.println("Portefeuille: Exception is caught");
Portefeuille p = new Portefeuille();
return p;
}
}
}
EDIT
I fixed it myself. Thanks for answering you all :)
You could define, on the top-level class, a method like getSortableValue(), and implement it to return a default field (you didn't mention the field you need to sort on for Woningen). In the KoopWoning you override this method to return the energyLevel instead. Then you always sort on the value returned by getSortableValue().
You can let the them implement Comparable, so like Woning implements Comparable<Woning>. This will let you implement the (required) method:
#override
public int compareTo(Woning other) {
int result = Integer.compareto(maxPrijs, other.maxPrijs);
if (result != 0) return result;
result = Integer.compareto(someField, other.someField);
if (result != 0) return result;
// etc...
return 0;
}
The subclass KoopWoning extends Woning implements Comparable<KoopWoning> can have a method like this:
#override
public int compareTo(KoopWoning other) {
int result = Integer.compareto(energylevel, other.energylevel);
if (result != 0) return result;
return super.compareTo(other);
}
Then all you need to do is load all the Woning instances in a list and execute
Collections.sort(list);
Having subclasses inherit Comparable is optional, so HuurWoning will just sort like Woning.
You could define a Comparator on Woning that determines the relative ordering of two Woning. You could do this either by having a method that looks at the actual types of the two arguments and then acts appropriately, or, better, by having an overrideable method of Woning that returns some value that you can use for sorting purposes.
If, for instance, you decide that anything with an energy level should come after anything without one, then you can have KoopWoning return something with the energy level in the high order bits of a long, so that it always comes out higher than anything without one (essentially you'd be setting a default energy level of zero).
Then, you can use
Collections.sort(arrayList, myComparator);
to sort the list based on the Comparator you've created.
There are some nice classes in the Guava library that help with Comparator building on multiple keys, but if your case is fairly simple, you probably won't need them.

Java compare strings that have characters and numbers

In Java , I want to compare and sort strings that contain a character and a number. For example:
A15, D35, A17, C45, B27, C30 should be sorted
A15 A17 B27 C30 C45 D35. I am not really sure how to compare two of those elements because they contain a string and a number. Can anyone help me please?
If your numbers are always two digits, then simply compare the whole things as strings. Numbers in decimal are strings too.
It's a different story if you need to sort A9, A54, and A123456 and want the numbers to sort by their numeric value. In that case you may need to write your own compare function that splits the string apart into its component parts.
An example of said compare function:
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import com.google.common.collect.Lists;
class Scratch {
public static void main(String[] args) {
final List<String> in = Lists.newArrayList("D35", "A1", "C7", "A25", "A131");
Collections.sort(in, new Comparator<String>() {
#Override
public int compare(String left, String right) {
int letter = Character.compare(left.charAt(0), right.charAt(0));
if (0 != letter)
return letter;
return Long.compare(Long.parseLong(left.substring(1)), Long.parseLong(right.substring(1)));
}
});
System.out.println(in);
}
}
Basically, if you need to sort list of string you can use streams:
List<String> yourSortedListOfStrings = yourListOfStrings.stream()
.sorted()
.collect(Collectors.toList());
public class StringComparator implements Comparator<String>{
String string_char[]= {"a","s","d","f","g","h","j","k","l","z","x","c","v","b","n","m","q","w","e","r","t","y","u","i","o","p"};
public enum DataType{
STRING,INTEGER,SPECIAL_CHAR;
}
public Integer getDataTypePriority(DataType type){
try{
switch (type) {
case SPECIAL_CHAR:
return 1;
case INTEGER:
return 2;
case STRING:
return 3;
default:
break;
}
}catch(Exception e){
e.printStackTrace();
}
return null;
}
public boolean isStringType(String val){
for(String temp: string_char)
if(temp.equalsIgnoreCase(val))
return true;
return false;
}
public DataType getDataType(Character val){
DataType type = null;
try{
Integer.parseInt(val.toString());
type = DataType.INTEGER;
}catch(Exception e){
if(isStringType(val.toString()))
type = DataType.STRING;
else
type = DataType.SPECIAL_CHAR;
}
return type;
}
#Override
public int compare(String new_val, String old_val) {
int result = 0;
try{
if(new_val == null)
return -1;
else if(old_val == null)
return 1;
StringBuilder old_Int = new StringBuilder();
StringBuilder new_Int = new StringBuilder();
DataType oldDataType = null;
DataType newDataType = null;
int old_length = old_val.length();
int new_length = new_val.length();
int max = old_length;
if(new_length < old_length)//equals
max = new_val.length();
StringBuilder old_Char = new StringBuilder();
StringBuilder new_Char = new StringBuilder();
for(int i=0;i<max;i++){
old_Char.setLength(0);
new_Char.setLength(0);
old_Char.append(old_val.charAt(i));
new_Char.append(new_val.charAt(i));
oldDataType = getDataType(old_val.charAt(i));
newDataType = getDataType(new_val.charAt(i));
if(oldDataType != newDataType){
if(getDataTypePriority(newDataType) > getDataTypePriority(oldDataType))
return 1;
else
return -1;
}else{//same
if(newDataType.equals(DataType.STRING)){
if(old_Int.length() >0){//clearing string builder
old_Int.setLength(0);
new_Int.setLength(0);
}
if(new_Char.toString().compareTo(old_Char.toString()) >0)
return 1;
else if(new_Char.toString().compareTo(old_Char.toString()) < 0)
return -1;
}else if(newDataType.equals(DataType.INTEGER)){
old_Int.append(old_val.charAt(i));
new_Int.append(new_val.charAt(i));
while(i+1<max){
i+=1;
oldDataType = getDataType(old_val.charAt(i));
newDataType = getDataType(new_val.charAt(i));
if(oldDataType.equals(DataType.INTEGER))
old_Int.append(old_val.charAt(i));
if(newDataType.equals(DataType.INTEGER))
new_Int.append(new_val.charAt(i));
if(oldDataType != newDataType)
break;
}
if(new_length > max){
while(i+1 < new_length){
i+=1;
newDataType = getDataType(new_val.charAt(i));
if(newDataType.equals(DataType.INTEGER))
new_Int.append(new_val.charAt(i));
else
break;
}
}else if(old_length >max){
while(i+1<old_length){
i+=1;
oldDataType = getDataType(old_val.charAt(i));
if(oldDataType.equals(DataType.INTEGER))
old_Int.append(old_val.charAt(i));
else
break;
}
}
Integer n = Integer.parseInt(new_Int.toString());
Integer o = Integer.parseInt(old_Int.toString());
if(n > o)
return 1;
else if(n < o)
return -1;
}else{//special char
if(old_Int.length() >0){//clearing string builder
old_Int.setLength(0);
new_Int.setLength(0);
}
if(new_Char.toString().compareTo(old_Char.toString()) >0)
return 1;
else if(new_Char.toString().compareTo(old_Char.toString()) < 0)
return -1;
}
}
}
return new_val.compareTo(old_val);
}catch(Exception e){
e.printStackTrace();
}
return result;
}
}

Categories