I am writing a program to merge sort words in a string.
But when I run my cod it seems to be loosing some data in some places.
I tested it with the string: "hello world the cat sat on the bloody mat"
but all i get back is [bloody, cat, hello, mat]
Here is my code:
package mergeSort;
import java.util.LinkedList;
public class mergeSort
{
public static String sort(String userInput)
{
if (userInput == null)
{
return "";
}
LinkedList<String> input = toList(userInput);
String output = MergeSort(input).toString();
return output;
}
private static LinkedList<String> toList(String input)
{
LinkedList<String> output = new LinkedList<String>();
String[] array = input.split("\\s");
for (String element : array)
{
output.addFirst(element);
}
return (output);
}
private static LinkedList<String> MergeSort(LinkedList<String> inputstring)
{
LinkedList<String> sequence1 = new LinkedList<String>();
LinkedList<String> sequence2 = new LinkedList<String>();
if (inputstring.size() <= 1)
{
return inputstring;
}
for (int index = 0; index <= (inputstring.size() / 2); index++)
{
sequence1.addLast(inputstring.removeFirst());
}
while (!(inputstring.isEmpty()))
{
sequence2.addLast(inputstring.removeFirst());
}
sequence1 = MergeSort(sequence1);
sequence2 = MergeSort(sequence2);
return merge(sequence1, sequence2);
}
private static LinkedList<String> merge(LinkedList<String> sequence1,
LinkedList<String> sequence2)
{
LinkedList<String> merged = new LinkedList<String>();
while (!(sequence1.isEmpty()) && !(sequence2.isEmpty()))
{
if (sequence1.peekFirst().compareTo(sequence2.peekFirst()) < 0)
{
merged.addLast(sequence1.removeFirst());
}
else
{
merged.addLast(sequence2.removeFirst());
}
}
while (!(sequence1.isEmpty()))
{
merged.addLast(sequence1.removeFirst());
}
while (!(sequence1.isEmpty()))
{
merged.addLast(sequence2.removeFirst());
}
return (merged);
}
}
The testerclass:
package mergeSort;
public class mainTester
{
public static void main(String[] args)
{
String test = "hello world the cat sat on the bloody mat";
System.out.println(mergeSort.sort(test));
System.exit(0);
}
}
The problem is here:
while (!(sequence1.isEmpty()))
{
merged.addLast(sequence1.removeFirst());
}
while (!(sequence1.isEmpty()))
{
merged.addLast(sequence2.removeFirst());
}
In your merge function. Both loops check sequence1 for emptiness. Replace the second sequence1 with sequence2 in the loop condition and all will be well.
Related
In this class I store a number and content belonging to this number. In the method deleteContentIfOlderThen() I check if the ArrayList(opexContent) is empty. But this works only if the check occurs inside the for loop. If I check it outside it doesn't work. I use a workStealingExecutorService to execute this method. But the list is only accessed by this class while the threads do the work.
So what am I doing wrong that it doesn't work outside the loop?
version with list.removeIf()
package org.excelAnalyser;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.function.Predicate;
public class OpexLine implements Runnable{
public static final int DELETE_CONTENT_TASK=0;
public final int SAPNumber;
public final ArrayList<String[]> opexContent;
private final DeletionRequestHandler m_deletionRequestHandler;
private String[] m_taskParameters=null;
private int m_taskid=-1;
public OpexLine(int SAPNumber, ArrayList<String[]> opexContent, DeletionRequestHandler deletionRequestHandler) {
this.SAPNumber=SAPNumber;
this.opexContent=opexContent;
m_deletionRequestHandler=deletionRequestHandler;
}
public void setupTask(int taskID, String[] parameters) {
m_taskid=taskID;
m_taskParameters=parameters;
}
public void run() {
if(m_taskid<0) {
System.out.println("aborted task because no taskID was given");
return;
}
if(m_taskParameters==null) {
System.out.println("no taskparameters were specified");
return;
}
switch (m_taskid) {
case DELETE_CONTENT_TASK:
deleteContentIfOlderThen();
break;
}
}
private void deleteContentIfOlderThen() {
final long unixTime=Long.parseLong(m_taskParameters[0]);
final int indexOfTime=Integer.parseInt(m_taskParameters[1]);
final SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");
final Date checkDate=new Date(System.currentTimeMillis()-unixTime);
opexContent.removeIf(new Predicate<String[]>() {
public boolean test(String[] content) {
final String timeString=content[indexOfTime];
if(timeString==null || timeString.isEmpty()) {
return false;
}
Date date = null;
try {
date = sdf.parse(timeString);
} catch (Exception e) {
return false;
//date = new Date();
}
return date.before(checkDate);
}
});
if(opexContent.isEmpty()) {
m_deletionRequestHandler.requestDeletionFor(this);
}
}
public String toString() {
final StringBuilder stringBuilder=new StringBuilder();
stringBuilder.append(SAPNumber);
stringBuilder.append(": ");
final int length=String.valueOf(SAPNumber).length();
//gen offset
final StringBuilder offsetBuilder=new StringBuilder();
for(int i=0; i<length+2; i++) {
offsetBuilder.append(' ');
}
final String offset=offsetBuilder.toString();
for (String[] strings : opexContent) {
for (String string : strings) {
stringBuilder.append(string+"; ");
}
stringBuilder.append("\n"+offset);
}
return stringBuilder.toString();
}
}
version with iterator:
package org.excelAnalyser;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
public class OpexLine implements Runnable{
public static final int DELETE_CONTENT_TASK=0;
public final int SAPNumber;
public final ArrayList<String[]> opexContent;
private final DeletionRequestHandler m_deletionRequestHandler;
private String[] m_taskParameters=null;
private int m_taskid=-1;
public OpexLine(int SAPNumber, ArrayList<String[]> opexContent, DeletionRequestHandler deletionRequestHandler) {
this.SAPNumber=SAPNumber;
this.opexContent=opexContent;
m_deletionRequestHandler=deletionRequestHandler;
}
public void setupTask(int taskID, String[] parameters) {
m_taskid=taskID;
m_taskParameters=parameters;
}
public void run() {
if(m_taskid<0) {
System.out.println("aborted task because no taskID was given");
return;
}
if(m_taskParameters==null) {
System.out.println("no taskparameters were specified");
return;
}
switch (m_taskid) {
case DELETE_CONTENT_TASK:
deleteContentIfOlderThen();
break;
}
}
private void deleteContentIfOlderThen() {
final long unixTime=Long.parseLong(m_taskParameters[0]);
final int indexOfTime=Integer.parseInt(m_taskParameters[1]);
final SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");
Iterator<String[]> opexContentIterator=opexContent.iterator();
contentLoop: while(opexContentIterator.hasNext()) {
String[] content=(String[])opexContentIterator.next();
final String timeString=content[indexOfTime];
if(timeString==null || timeString.isEmpty()) {
continue contentLoop;
}
Date date = null;
try {
date = sdf.parse(timeString);
} catch (Exception e) {
continue contentLoop;
//date = new Date();
}
Date checkDate=new Date(System.currentTimeMillis()-unixTime);
if(date.before(checkDate)) {
opexContentIterator.remove();
}
}
if(opexContent.isEmpty()) {
m_deletionRequestHandler.requestDeletionFor(this);
}
}
public String toString() {
final StringBuilder stringBuilder=new StringBuilder();
stringBuilder.append(SAPNumber);
stringBuilder.append(": ");
final int length=String.valueOf(SAPNumber).length();
//gen offset
final StringBuilder offsetBuilder=new StringBuilder();
for(int i=0; i<length+2; i++) {
offsetBuilder.append(' ');
}
final String offset=offsetBuilder.toString();
for (String[] strings : opexContent) {
for (String string : strings) {
stringBuilder.append(string+"; ");
}
stringBuilder.append("\n"+offset);
}
return stringBuilder.toString();
}
}
version without iterator:
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
public class OpexLine implements Runnable{
public static final int DELETE_CONTENT_TASK=0;
public final int SAPNumber;
public final ArrayList<String[]> opexContent;
private final DeletionRequestHandler m_deletionRequestHandler;
private String[] m_taskParameters=null;
private int m_taskid=-1;
public OpexLine(int SAPNumber, ArrayList<String[]> opexContent, DeletionRequestHandler deletionRequestHandler) {
this.SAPNumber=SAPNumber;
this.opexContent=opexContent;
m_deletionRequestHandler=deletionRequestHandler;
}
public void setupTask(int taskID, String[] parameters) {
m_taskid=taskID;
m_taskParameters=parameters;
}
public void run() {
if(m_taskid<0) {
System.out.println("aborted task because no taskID was given");
return;
}
if(m_taskParameters==null) {
System.out.println("no taskparameters were specified");
return;
}
switch (m_taskid) {
case DELETE_CONTENT_TASK:
deleteContentIfOlderThen();
break;
}
}
private void deleteContentIfOlderThen() {
final long unixTime=Long.parseLong(m_taskParameters[0]);
final int indexOfTime=Integer.parseInt(m_taskParameters[1]);
final SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");
contentLoop: for(final String[] content : opexContent) {
//final String[] content=opexContent.get(i);
final String timeString=content[indexOfTime];
if(timeString==null || timeString.isEmpty()) {
continue contentLoop;
}
Date date = null;
try {
date = sdf.parse(timeString);
} catch (Exception e) {
continue contentLoop;
//date = new Date();
}
Date checkDate=new Date(System.currentTimeMillis()-unixTime);
//System.out.println(date+" before "+checkDate+": "+date.before(checkDate));
if(date.before(checkDate)) {
System.out.println("removed");
opexContent.remove(content);
if(opexContent.isEmpty()) {
System.out.println("isEmptyAfterRemoval");
m_deletionRequestHandler.requestDeletionFor(this);
}
}
}
//System.out.println("isexecuted");
if(opexContent.isEmpty()) {
System.out.println("isEmpty");
m_deletionRequestHandler.requestDeletionFor(this);
}
}
public String toString() {
final StringBuilder stringBuilder=new StringBuilder();
stringBuilder.append(SAPNumber);
stringBuilder.append(": ");
final int length=String.valueOf(SAPNumber).length();
//gen offset
final StringBuilder offsetBuilder=new StringBuilder();
for(int i=0; i<length+2; i++) {
offsetBuilder.append(' ');
}
final String offset=offsetBuilder.toString();
for (String[] strings : opexContent) {
for (String string : strings) {
stringBuilder.append(string+"; ");
}
stringBuilder.append("\n"+offset);
}
return stringBuilder.toString();
}
}
You should never mutate a list while you are iterating it. This type of code:
final ArrayList<String[]> opexContent;
private void deleteContentIfOlderThen() {
for(final String[] content : opexContent) {
Date date = /* some date */;
Date checkDate=new Date(System.currentTimeMillis()-unixTime);
if(date.before(checkDate)) {
opexContent.remove(content); //CME!
}
}
}
Will likely cause a ConcurrentModificationException, as the list was mutated while an Iterator was in use (behind the scenes). Instead, you should use the Iterator directly, such that you have the ability to use Iterator#remove:
final ArrayList<String[]> opexContent;
private void deleteContentIfOlderThen() {
Iterator<String[]> itr = opexContent.iterator();
while (itr.hasNext()) {
String[] content = itr.next();
Date date = /* some date */;
Date checkDate=new Date(System.currentTimeMillis()-unixTime);
if(date.before(checkDate)) {
itr.remove(); //No more CME!
}
}
}
Whilst Rogue's answer is correct in saying that you shouldn't remove elements from the list while iterating it, there's a neater way of removing the elements since Java 8 that avoids using an iterator explicitly:
// Doesn't have to be moved outside, but at least doing this means
// you're comparing against a fixed check date, rather than potentially
// changing as you iterate.
Date checkDate=new Date(System.currentTimeMillis()-unixTime);
opexContent.removeIf(content -> {
Date date = /* some date */;
return date.before(checkDate);
});
This is better because
it's clearer, because you're not having to deal with the iterator
it's safer, as it leaves the list untouched if an exception is thrown for some element (i.e. it's failure atomic);
it's more efficient, because it avoids resizing the list repeatedly
Code: Search word in Trie
Implement the function SearchWord for the Trie class.
For a Trie, write the function for searching a word. Return true if the word is found successfully, otherwise return false.
Note: main function is given for your reference which we are using internally to test the code.
class TrieNode{
char data;
boolean isTerminating;
TrieNode children[];
int childCount;
public TrieNode(char data) {
this.data = data;
isTerminating = false;
children = new TrieNode[26];
childCount = 0;
}
}
public class Trie {
private TrieNode root;
public int count;
public Trie() {
root = new TrieNode('\0');
count = 0;
}
private boolean add(TrieNode root, String word){
if(word.length() == 0){
if (!root.isTerminating) {
root.isTerminating = true;
return true;
} else {
return false;
}
}
int childIndex = word.charAt(0) - 'a';
TrieNode child = root.children[childIndex];
if(child == null){
child = new TrieNode(word.charAt(0));
root.children[childIndex] = child;
root.childCount++;
}
return add(child, word.substring(1));
}
public void add(String word){
if (add(root, word)) {
this.count++;
}
}
public boolean search(String word){
// add your code here
return search(root,word);
}
private boolean search(TrieNode root, String word){
if(word.length()==0){
return true;
}
int childIndex = word.charAt(0) -'a';
TrieNode child = root.children[childIndex];
if(child==null){
return false;
}
return search(child, word.substring(1));
}
}
//Main Function
code
import java.io.*;
public class Runner {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
public static void main(String[] args) throws IOException{
Trie t = new Trie();
String[] string = br.readLine().split("\\s");
int choice = Integer.parseInt(string[0]);
String word = "Null";
if (string.length!=1)
{
word = string[1];
}
while(choice != -1) {
switch(choice) {
case 1 : // insert
t.add(word);
break;
case 2 : // search
System.out.println(t.search(word));
break;
default :
return;
}
string = br.readLine().split("\\s");
choice = Integer.parseInt(string[0]);
if (string.length!=1)
{
word = string[1];
}
}
}
}
You need to make use of the isTerminating information. In search, change:
if(word.length()==0){
return true;
}
To:
if(word.length()==0){
return root.isTerminating;
}
I'm trying to write a code that split a spaceless string into meaningful words but when I give sentence like "arealways" it returns ['a', 'real', 'ways'] and what I want is ['are', 'always'] and my dictionary contains all this words. How can I can write a code that keep backtracking till find the best matching?
the code that returns 'a', 'real', 'ways':
splitter.java:
public class splitter {
HashMap<String, String> map = new HashMap<>();
Trie dict;
public splitter(Trie t) {
dict = t;
}
public String split(String test) {
if (dict.contains(test)) {
return (test);
} else if (map.containsKey(test)) {
return (map.get(test));
} else {
for (int i = 0; i < test.length(); i++) {
String pre = test.substring(0, i);
if (dict.contains(pre)) {
String end = test.substring(i);
String fixedEnd = split(end);
if(fixedEnd != null){
map.put(test, pre + " " + fixedEnd);
return pre + " " + fixedEnd;
}else {
}
}
}
}
map.put(test,null);
return null;
}
}
Trie.java:
public class Trie {
public static class TrieNode {
private HashMap<Character, TrieNode> charMap = new HashMap<>();
public char c;
public boolean endOWord;
public void insert(String s){
}
public boolean contains(String s){
return true;
}
}
public TrieNode root;
public Trie() {
root = new TrieNode();
}
public void insert(String s){
TrieNode p = root;
for(char c : s.toCharArray()) {
if(! p.charMap.containsKey(c)) {
TrieNode node = new TrieNode();
node.c = c;
p.charMap.put(c, node);
}
p = p.charMap.get(c);
}
p.endOWord = true;
}
public boolean contains(String s){
TrieNode p = root;
for(char c : s.toCharArray()) {
if(!p.charMap.containsKey(c)) {
return false;
}
p = p.charMap.get(c);
}
return p.endOWord;
}
public void insertDictionary(String filename) throws FileNotFoundException{
File file = new File(filename);
Scanner sc = new Scanner(file);
while(sc.hasNextLine())
insert(sc.nextLine());
}
public void insertDictionary(File file) throws FileNotFoundException{
Scanner sc = new Scanner(file);
while(sc.hasNextLine())
insert(sc.nextLine());
}
}
WordSplitter class:
public class WordSplitter {
public static void main(String[] args) throws FileNotFoundException {
String test = "arealways";
String myFile = "/Users/abc/Desktop/dictionary.txt";
Trie dict = new Trie();
dict.insertDictionary(myFile);
splitter sp = new splitter(dict);
test = sp.split(test);
if(test != null)
System.out.println(test);
else
System.out.println("No Splitting Found.");
}
}
Using the OP's split method and the implementation of Trie found in The Trie Data Structure in Java Baeldung's article, I was able to get the following results:
realways=real ways
arealways=a real ways
However, if I remove the word "real" or "a" from the dictionary, I get the following results:
realways=null
arealways=are always
Here's the entire code I used to get these results:
public class Splitter {
private static Map<String, String> map = new HashMap<>();
private Trie dict;
public Splitter(Trie t) {
dict = t;
}
/**
* #param args
*/
public static void main(String[] args) {
List<String> words = List.of("a", "always", "are", "area", "r", "way", "ways"); // The order of these words does not seem to impact the final result
String test = "arealways";
Trie t = new Trie();
for (String word : words) {
t.insert(word);
}
System.out.println(t);
Splitter splitter = new Splitter(t);
splitter.split(test);
map.entrySet().forEach(System.out::println);
}
public String split(String test) {
if (dict.find(test)) {
return (test);
} else if (map.containsKey(test)) {
return (map.get(test));
} else {
for (int i = 0; i < test.length(); i++) {
String pre = test.substring(0, i);
if (dict.find(pre)) {
String end = test.substring(i);
String fixedEnd = split(end);
if (fixedEnd != null) {
map.put(test, pre + " " + fixedEnd);
return pre + " " + fixedEnd;
} else {
}
}
}
}
map.put(test, null);
return null;
}
public static class Trie {
private TrieNode root = new TrieNode();
public boolean find(String word) {
TrieNode current = root;
for (int i = 0; i < word.length(); i++) {
char ch = word.charAt(i);
TrieNode node = current.getChildren().get(ch);
if (node == null) {
return false;
}
current = node;
}
return current.isEndOfWord();
}
public void insert(String word) {
TrieNode current = root;
for (char l : word.toCharArray()) {
current = current.getChildren().computeIfAbsent(l, c -> new TrieNode());
}
current.setEndOfWord(true);
}
#Override
public String toString() {
return toString(root);
}
/**
* #param root2
* #return
*/
private String toString(TrieNode node) {
return node.toString();
}
public static class TrieNode {
private Map<Character, TrieNode> children = new HashMap<>() ;
private String contents;
private boolean endOfWord;
public Map<Character, TrieNode> getChildren() {
return children;
}
public void setEndOfWord(boolean endOfWord) {
this.endOfWord = endOfWord;
}
public boolean isEndOfWord() {
return endOfWord;
}
#Override
public String toString() {
StringBuilder sbuff = new StringBuilder();
if (isLeaf()) {
return sbuff.toString();
}
children.entrySet().forEach(entry -> {
sbuff.append(entry.getKey() + "\n");
});
sbuff.append(" ");
return children.toString();
}
private boolean isLeaf() {
return children.isEmpty();
}
}
public void delete(String word) {
delete(root, word, 0);
}
private boolean delete(TrieNode current, String word, int index) {
if (index == word.length()) {
if (!current.isEndOfWord()) {
return false;
}
current.setEndOfWord(false);
return current.getChildren().isEmpty();
}
char ch = word.charAt(index);
TrieNode node = current.getChildren().get(ch);
if (node == null) {
return false;
}
boolean shouldDeleteCurrentNode = delete(node, word, index + 1) && !node.isEndOfWord();
if (shouldDeleteCurrentNode) {
current.getChildren().remove(ch);
return current.getChildren().isEmpty();
}
return false;
}
}
}
I improved the original code by adding a toString() method to the Trie and TrieNode. Now, when I print out the Trie object "t", I get the following result:
{a={r={e={a=}}, l={w={a={y={s=}}}}}, w={a={y={s=}}}}
My conclusion is that the OP's TrieNode implementation is incorrect. The way the Trie is built, given the inputted string value, the behavior described by the OP seems to be correct.
I have a text file as below:
Pen 100
Ink 50
Pen 150
Paper 20
and I want to sum each of the goods
the output should look like:
Pen 250
Ink 50
Paper 20
Max Pen 250
Min Paper 20
I write just only some code below and I stuck:
public static void readData(){
File infile = new File("D:\\itemData.txt");
String itemName = new String();
String[] nameList = new String[100];
String[] saleList = new String[100];
int sale;
int count =0;
try {
Scanner data = new Scanner(infile);
while (data.hasNext()) {
itemName = data.next();
sale = data.nextInt();
nameList[count] = name;
saleList[count] = String.valueOf(sale);
count++;
for (int i = 0; i < nameList.length; i++) {
if (nameList[i] != null) {
System.out.println(nameList[i] + " " + saleList[i]);
}
}
data.close();
}
} catch (IOException e) {
}}
Try the code below.
There were 2 issues in the code I could see.
a) You did not declare the variable count
b) You were printing while reading the data, and that is not desirable.
public static void readData(){
File infile = new File("D:\\itemData.txt");
String itemName = new String();
String[] nameList = new String[100];
String[] saleList = new String[100];
int sale;
int count = 0;
try {
Scanner data = new Scanner(infile);
while (data.hasNext()) {
itemName = data.next();
sale = data.nextInt();
nameList[count] = name;
saleList[count] = String.valueOf(sale);
count++;
data.close();
}
} catch (SIOException e) {
}
for (int i = 0; i < nameList.length; i++) {
if (nameList[i] != null) {
System.out.println(nameList[i] + " " + saleList[i]);
}
}
}
Also consider implementing something like this to keep track of maxes and mins for you:
package com.example.demo;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.commons.collections4.map.HashedMap;
public class Inventory {
private Map<String, AtomicInteger> totals = new HashedMap<>();
private Map<String, AtomicInteger> maxes = new HashedMap<>();
private Map<String, AtomicInteger> mins = new HashedMap<>();
public void add(String name, int number) {
getOrCreateFromMap(totals, name, 0).addAndGet(number);
getOrCreateFromMap(maxes, name, Integer.MIN_VALUE).getAndUpdate(present -> (present < number) ? number : present);
getOrCreateFromMap(mins, name, Integer.MAX_VALUE).getAndUpdate(present -> (number < present) ? number : present);
}
private AtomicInteger getOrCreateFromMap(Map<String, AtomicInteger> map, String name, int initialValue) {
return map.computeIfAbsent(name, x -> new AtomicInteger(initialValue));
}
public int getTotal(String name) {
return getFromMap(totals, name);
}
public int getMax(String name) {
return getFromMap(maxes, name);
}
public int getMin(String name) {
return getFromMap(mins, name);
}
private int getFromMap(Map<String, AtomicInteger> map, String key) {
return map.computeIfAbsent(key, x -> new AtomicInteger())
.get();
}
public static void main(String[] args) {
Inventory i = new Inventory();
i.add("paper", 50);
i.add("paper", 150);
System.out.println(i.getTotal("paper"));
System.out.println(i.getMax("paper"));
System.out.println(i.getMin("paper"));
}
}
Here is a working example, for the mentioned problem statement -
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Map;
import java.util.stream.Collectors;
public class ReadAndSumFileData {
public static void main(String... arguments) throws IOException {
String filename = "C:/temp/SalesData.txt";
readData(filename);
}
private static void readData(String filename) throws IOException {
Map<String, Integer> map = Files.lines(Paths.get(filename))
.map(s -> s.split("\\s+"))
.collect(Collectors.groupingBy(a -> a[0], Collectors.summingInt(a -> Integer.parseInt(a[1]))));
map.entrySet().stream().forEach(e-> System.out.println(e));
}
}
I am trying to get the GETTER of "FileHandler.java" to return the value(final_match) to "main.java" and out put. Problem is that final_match outputs as 0. In "FileHandler.java" Outside of my getter final_match has the correct value, but when called/returned from the GETTER value is plain 0
main.java
package textreader;
import java.io.File;
import java.util.ArrayList;
import java.util.Scanner;
public class main {
public String data = "";
public static void main(String[] args) {
Scanner user_input = new Scanner(System.in);
final File directory = new File("E:\\test\\filename.txt");
// final File directory2 = new File("E:\\test\\filename2.txt");
ArrayList<File> f = new ArrayList<>();
f.add(directory);
// f.add(directory2);
final String words;
System.out.println("The word you would like to search for. ");
System.out.println("----------------------------------------");
words = user_input.next();
main aMain = new main(f, words);
}
main(ArrayList<File> f, String words) { //constructor
ArrayList<FileHandler> threadArray = new ArrayList<>();//arraylist of type filehandler
for (File file : f) {
FileHandler fh = new FileHandler(this, words, file);// instance of filehandler = fh
threadArray.add(fh);
fh.start();
for (FileHandler x : threadArray) {
if (x.isFinished()) {
x.setFinished(true);
synchronized (x) {
x.notify();// notify next thread to continue
}
}
int answer = x.getfinal_match(); // CALLING THE GETTER FOR VALUE
System.out.println("----------------------------------------");
System.out.println("this word has appeared: " + answer + " times.");
System.out.println("----------------------------------------");
}
}
}
}
FileHander.java
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class FileHandler extends Thread {
BufferedReader br = null;
FileReader fr = null;
String words;
File file;
int counter;
int match;
int final_match;
boolean done = true;
boolean finished;
private final main main;
public FileHandler(main instance, String words, File file) { //constructor
this.words = words;
this.file = file;
this.main = instance;
}
#Override
public synchronized void run() {
try {
fr = new FileReader(this.file);//file path
br = new BufferedReader(fr);// reads the words in the file
String theLine;
while ((theLine = br.readLine()) != null) {
String List[] = theLine.split(" ");
for (String List1 : List) {
if (List1.equals(List[counter])) {// of words are the same as "word" increment match
match++; //Amount of occurrences
}
counter++;//loop through each word
}
synchronized (this) {
//System.out.println("test2 " + match);
this.finished = true;
}
}
} catch (IOException e) {
} finally {
try {
if (br != null) {
br.close();
}
if (fr != null) {
fr.close();
}
} catch (IOException ex) {
}
}
final_match = match;
System.out.println("testing " + final_match); // THIS TEST WORKS AS VALUE WAS OUTPUTTED AS 5
}
public void setfinal_match(int test) {
final_match = test;
}
public Integer getfinal_match() {
System.out.println("testing 123456 " + final_match); // THIS VALUE DOES NOT WORK AS IT OUTPUTS A BIG FAT 0
return final_match;
}
public boolean isFinished() {
return this.finished;
}
public void setFinished(boolean finished) {
this.finished = finished;
}
}
//OUTPUT
//run:
//the word you would like to search for.
//----------------------------------------
//dog
//testing GETTER 123456 0
//----------------------------------------
//this word has appeared: 0 times.
//----------------------------------------
//testing 5
//BUILD SUCCESSFUL (total time: 2 seconds)
//EXPECTED OUTPUT
//run:
//The word you would like to search for.
//----------------------------------------
//dog
//testing GETTER 123456 5
//----------------------------------------
//this word has appeared: 5 times. (THIS IS THE MAIN VALUE THAT HAS TO CHANGE)
//----------------------------------------
//testing 5
//BUILD SUCCESSFUL (total time: 2 seconds)
Your final_match is 0 at the time of the output, since the thread starts and is not finished yet, when you output the value of final_match.