My code has to read 50 lines of input and output them in reverse order, then other 50 lines, so output starts from 50th line, goes to the 1st one, then it start from 100th line to 50th I got it to work. But the only thing, that 51 line isn't printed, I can't get what's going wrong.
public static void doIt(BufferedReader r, PrintWriter w) throws IOException {
String newString;
LinkedList<String> list = new LinkedList<String>();
int i = 0;
while ((newString = r.readLine()) != null) {
if (i < 50) {
i++;
list.addFirst(newString);
} else {
for (String s : list)
w.println(s);
list.clear();
i = 0;
}
}
for (String s : list)
w.println(s);
}
Change your code as follow:
i++;
list.addFirst(newString);
to
list.addFirst(newString);
i++;
Because the way you are adding newString to list will skip one count
Update:
Sorry but I have to fix my answer rather than deleting this. I checked it twice and as per the right answer add this line :-)
list.addFirst(newString);
You are discarding the line you read when i == 50, here is a fix that makes it work.
public static void doIt(BufferedReader r, PrintWriter w) throws IOException {
String newString;
LinkedList<String> list = new LinkedList<String>();
int i = 0;
while ((newString = r.readLine()) != null) {
if (i < 50) {
i++;
list.addFirst(newString);
} else {
for (String s : list)
w.println(s);
list.clear();
list.addFirst(newString); // <---- add this line and you should be fine
i = 0;
}
}
for (String s : list)
w.println(s);
}
Related
I am trying to write a program that has the method public static void method(List<String> words) where the parameter words is a list of words from the text file words.txt that are sorted and contain only the words where each letter occurs only once. For example, the word "feel" would not be included in this list since "e" occurs more than once. The word list is not to be used as an argument in the rest of the program, so the method method is only to be used to store and remember the wordlist for later use. This function can also perform any of the sorting methods.
My thought process was to create a method that would read the text file, and use that text file as the argument in method. method would then filter out all words with letters that appear more than once, and also sort the new list.
When running the program, I'm getting an error "java.util.ConcurrentModificationException: null (in java.util.LinkedList$Listltr)" on the line for (String word : words). Also does the line public static List list; properly save and store the list for later use?
import java.util.*;
import java.io.*;
class ABC
{
public static List<String> list = new LinkedList<String>()
public static List readFile()
{
String content = new String();
File file = new File("words.txt");
LinkedList<String> words = new LinkedList<String>();
try
{
Scanner sc = new Scanner(new FileInputStream(file));
while (sc.hasNextLine())
{
content = sc.nextLine();
words.add(content);
}
}
catch (FileNotFoundException fnf)
{
fnf.printStackTrace();
}
catch (Exception e)
{
e.printStackTrace();
System.out.println("\nProgram terminated safely");
}
for (String word : words)
{
if (letters(word) == false)
{
list.add(word);
}
}
Collections.sort(list);
return list;
}
public static boolean letters(String word)
{
for (int i = 0; i < word.length() - 1; i++)
{
if (word.contains(String.valueOf(word.charAt(i))) == true)
{
return true;
}
}
return false;
}
public static void main(String args[])
{
System.out.println(readFile());
}
}
The source of the error is that you are changing a list that you are iterating on. This is generally not a good idea.
Since you are building a new list, you don't actually need to change the one you are iterating on. I would recommend changing your code so that the logic for deciding if a letter appears more than once goes in a separate method. This way the complexity of any given method is manageable, and you can test them separately.
So create a new method that tests if any letter appears more than once:
static boolean doesAnyLetterAppearMoreThanOnce(String word) {
...
}
Then you can use it in your existing method:
for (String word : words) {
if (!doesAnyLetterAppearMoreThanOnce(word)) {
list.add(word);
}
}
Collections.sort(list);
Use an iterator. Try it like this.
Iterator<String> it = words.iterator();
while(it.hasNext()) {
CharSequence ch = it.next();
for (int j = 0; j < ch.length(); j++)
{
for (int k = j + 1; k < ch.length(); k++)
{
if (ch.charAt(j) == ch.charAt(k))
{
it.remove(word);
}
}
}
list.add(word);
}
However, I would approach it differently.
String[] data =
{ "hello", "bad", "bye", "computer", "feel", "glee" };
outer: for (String word : data) {
for (int i = 0; i < word.length() - 1; i++) {
if (word.charAt(i) == word.charAt(i + 1)) {
System.out.println("dropping '" + word + "'");
continue outer;
}
}
System.out.println("Keeping '" + word + "'");
List.add(word);
}
Note: You used feel as an example so it wasn't clear if you wanted to check for the same letter anywhere in the word or only adjacent letters that are the same.
There are several problems with you program:
public static List list;
Whenever you see a collection (like List) without a generics - it's a bad smell. Should be public static List<String> list;
Also consider changing public to private.
In readFile() method you mask the class variable 'list' with a local variable 'list'. So your class variable remains uninitialized:
list = new LinkedList<String>();
Better use try-with-resources for scanner:
try(Scanner sc = new Scanner(new FileInputStream(file))) {
You don't need to close it afterwards manually.
You cannot modify the list through which you are iterating. You should either use an iterator and its remove method, or create a new list and append good words to it, instead of removing bad words from the original list.
public static List<String> readFile() {
File file = new File("words.txt");
List<String> list = new ArrayList<>();
try (Scanner scanner = new Scanner(file)) {
while (scanner.hasNextLine()) {
String word = scanner.nextLine();
if (noDuplicates(word)) {
list.add(word);
}
}
Collections.sort(list);
} catch (FileNotFoundException e) {
System.out.println("File not found");
}
return list;
}
private static boolean noDuplicates(String word) {
Set<Character> distinctChars = new HashSet<>();
for (char c : word.toCharArray()) {
if (!distinctChars.add(c)) {
return false;
}
}
return true;
}
I suggest this shorter approach:
public static void method(List<String> words) {
words.removeIf(word -> {
Set<Integer> hs = new HashSet<>();
return word.chars().anyMatch(c -> {
if (hs.contains(c)) return true;
else hs.add(c);
return false;
});
});
System.out.println(words);}
words List now contain only the words where each letter occurs only once.
So i've been trying to take a txt file which has input like this for eg -
abcddhdj
efghdd
ijkl
to get this -
j
d
hd
dd
dhl
cgk
bfj
aei
i have tried to do this using 2d char array which gave nullexception and arrayoutofbound error and didnt work mostly,then tried string array , arraylist of arraylist of char , and lastly i have been trying using arraylsit of string
here is the closest i got to my solution after lot of searching by using string[] -
public static void main(String[] args) throws IOException
{
BufferedReader br = new BufferedReader(new FileReader("C:\\test.txt")); // PUT YOUR FILE LOCATION HERE
int k=0,i,j=0,x;
String line[] = new String[10] ; //SET THE APPROXIMATE NUMBER OF ROWS
while((line[k] = br.readLine()) !=null)
{System.out.println(line[k]); //print to check input - verified
k++;
}
for(x=0;x<k;x++)
{if(j<line[x].length())
{j=line[x].length()-1;} //this part not working in above loop
}
System.out.println(j); // verified but not working inside previous loop for some reason
System.out.println(k);
for(x=j-1;x>=0;x++) //without this loop,its perfect, but with it gives indexoutofbound error , doesnt run at x=j
{ for(i=0;i<k;i++)
{ System.out.print(line[i].charAt(x));
}
System.out.println();
}
}
here is one output
run:
abcd
efgh
ijkl
4 //should have come as 3 since i did length-1
3
chl //notice the d missing , every char of first row shifted,just why
bgk //in outofbound error , it only prints d at the end, need explanation
afj
ei
BUILD SUCCESSFUL (total time: 0 seconds)
if i add a space after abcd it gives indexoutofbound and no output after k
at end i used another method which adds spaces to make all length equal
yet still the output was wrong, plus there is something wrong with this way of thinking , there should be better method
so i tried arraylist , this is giving me more problems again
trying to work this out by any method understandable.
This ought to do the trick:
The key here is that I pad all the line arrays with empty chars so that each character array is the same length as the longest line.
public static void main(String[] args)
{
try (BufferedReader br = new BufferedReader(new FileReader("C:\\test.txt")))
{
String line;
List<List<Character>> lines = new ArrayList<>();
int longestLine = 0;
while((line = br.readLine()) !=null)
{
line = line.trim();
if (line.length() > 0)
{
List<Character> currList = new ArrayList<>();
for (char c : line.toCharArray())
{
currList.add(c);
}
if (currList.size() > longestLine)
{
longestLine = currList.size();
}
lines.add(currList);
}
}
// pad all lists to be the same as the longest
for (List<Character> currList : lines)
{
while (currList.size() < longestLine)
{
currList.add(Character.MIN_VALUE);
}
}
// go through each list backwards
for (int i = longestLine - 1; i >= 0; i-- )
{
for (List<Character> currList : lines)
{
System.out.print(currList.get(i));
}
System.out.println();
}
}
catch (Throwable t)
{
t.printStackTrace();
}
}
Example Input:
abcd
efgh
ijkl
g
Example Output:
dhl
cgk
bfj
aeig
Assuming input is read into the arraylist
ArrayList<String> inputList = new ArrayList<String>();
inputList.add("abcddhdj");
inputList.add("efghdd");
inputList.add("ijkl");
int maxSize = 0;
for (String input : inputList) {
if (input.length() > maxSize) {
maxSize = input.length();
}
}
String outputList[] = new String[maxSize];
for (int i = 0; i < maxSize; i++) {
String output = "";
for (String input : inputList) {
if(i<input.length())
output=output+input.charAt(i);
}
outputList[maxSize-(i+1)]=output;
}
Store all to direct 2d array and transpose in printing loop
final char[][] matrix = Files.lines(Paths.get(fileName)).map(String::toCharArray).toArray(char[][]::new);
final int width = Arrays.stream(matrix).mapToInt(a -> a.length).max().getAsInt();
for (int i = 0; i < width; ++i ) {
final int idx = width-i-1;
String s = Arrays.stream(matrix).map(a -> a.length > idx ? String.valueOf(a[idx]) : " ").collect(Collectors.joining());
System.out.println(s);
}
I would like to make the following code faster, without changing the reading/writing from standard console. The first line contains the number of inputs and the subsequent lines contain a set of Integers.
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws java.lang.Exception {
try {
java.io.BufferedReader r = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));
int a = Integer.parseInt(r.readLine());
for (int i = 0; i < a; i++) {
StringTokenizer st = new StringTokenizer(r.readLine());
while (st.hasMoreTokens()) {
int first = Integer.parseInt(st.nextToken());
int second = Integer.parseInt(st.nextToken());
if (first < second)
System.out.println("<");
else if (first > second)
System.out.println(">");
else
System.out.println("=");
}
}
} catch (Exception e) {
System.err.print(e.getMessage());
}
}
}
You are performing a lot of redundant autoboxing and outboxing there which could be saved if you define first and second as primitive ints instead of java.lang.Integer wrapper classes. I doubt, however, that for any reasonable size of input you'd even notice the difference.
Here are a few suggestions, I am not sure these will help a lot.
1) This,
if (first < second)
System.out.println("<");
else if (first > second)
System.out.println(">");
else
System.out.println("=");
can be changed to
System.out.println(first < second
? "<"
: first > second
? ">"
: "="
);
2) Since you are using a throws clause and your try-catch does nothing you can remove it.
3) Here,
int first = Integer.parseInt(st.nextToken());
int second = Integer.parseInt(st.nextToken());
You are not checking for hasMoreTokens() the second time.
4) Use split() instead of StringTokenizer. More on that here and here.
You may consider to use the BufferedReader's constructor below:
public BufferedReader(Reader in, int sz)
Giving the sz parameter a reasonable high value, can avoid the buffer to be refilled too often.
As a side note, while readLine() retuns null if the end of the stream has been reached, it's better to check its return value before calling new StringTokenizer(r.readLine()) and Integer.parseInt(r.readLine()).
The edited class follows:
public class Main {
public static void main(String[] args) {
BufferedReader r;
String line;
StringTokenizer st;
int a, first, second;
r = new BufferedReader(new InputStreamReader(System.in), 4096);
try {
line = r.readLine();
if (line != null) {
a = Integer.parseInt(line);
for (int i = 0; i < a; ++i) {
line = r.readLine();
if (line == null)
break;
st = new StringTokenizer(line);
while (st.hasMoreTokens()) {
first = Integer.parseInt(st.nextToken());
second = Integer.parseInt(st.nextToken());
if (first < second)
System.out.println("<");
else if (first > second)
System.out.println(">");
else
System.out.println("=");
}
}
}
r.close();
} catch (Exception e) {
System.err.print(e.getMessage());
}
}
}
What is the correct syntax for searching an ArrayList of strings for a single character? I want to check each string in the array for a single character.
Ultimately I want to perform multiple search and replaces on all strings in an array based on the presence of a single character in the string.
I have reviewed java-examples.com and java docs as well as several methods of searching ArrayLists. None of them do quite what I need.
P.S. Any pointers on using some sort of file library to perform multiple search and replaces would be great.
--- Edit ---
As per MightyPork's recommendations arraylist revised to use simple string type. This also made it compatible with hoosssein's solution which is included.
public void ArrayInput() {
String FileName; // set file variable
FileName = fileName.getText(); // get file name
ArrayList<String> fileContents = new ArrayList<String>(); // create arraylist
try {
BufferedReader reader = new BufferedReader(new FileReader(FileName)); // create reader
String line = null;
while ((line = reader.readLine()) != null) {
if(line.length() > 0) { // don't include blank lines
line = line.trim(); // remove whitespaces
fileContents.add(line); // add to array
}
}
for (String row : fileContents) {
System.out.println(row); // print array to cmd
}
String oldstr;
String newstr;
oldstr = "}";
newstr = "!!!!!";
for(int i = 0; i < fileContents.size(); i++) {
if(fileContents.contains(oldstr)) {
fileContents.set(i, fileContents.get(i).replace(oldstr, newstr));
}
}
for (String row : fileContents) {
System.out.println(row); // print array to cmd
}
// close file
}
catch (IOException ex) { // E.H. for try
JOptionPane.showMessageDialog(null, "File not found. Check name and directory.");
}
}
first you need to iterate the list and search for that character
string.contains("A");
for replacing the character you need to keep in mind that String is immutable and you must replace new string with old string in that list
so the code is like this
public void replace(ArrayList<String> toSearchIn,String oldstr, String newStr ){
for(int i=0;i<toSearchIn.size();i++){
if(toSearchIn.contains(oldstr)){
toSearchIn.set(i, toSearchIn.get(i).replace(oldstr, newStr));
}
}
}
For the search and replace you are better off using a dictionary, if you know that you will replace Hi with Hello. The first one is a simple search, here with the index and the string being returned in a Object[2], you will have to cast the result. It returns the first match, you were not clear on this.
public static Object[] findStringMatchingCharacter(List<String> list,
char character) {
if (list == null)
return null;
Object[] ret = new Object[2];
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
if (s.contains("" + character)) {
ret[0] = s;
ret[1] = i;
}
return ret;
}
return null;
}
public static void searchAndReplace(ArrayList<String> original,
Map<String, String> dictionary) {
if (original == null || dictionary == null)
return;
for (int i = 0; i < original.size(); i++) {
String s = original.get(i);
if (dictionary.get(s) != null)
original.set(i, dictionary.get(s));
}
}
You can try this, modify as needed:
public static ArrayList<String> findInString(String needle, List<String> haystack) {
ArrayList<String> found = new ArrayList<String>();
for(String s : haystack) {
if(s.contains(needle)) {
found.add(s);
}
}
return found;
}
(to search char, just do myChar+"" and you have string)
To add the find'n'replace functionality should now be fairly easy for you.
Here's a variant for searching String[]:
public static ArrayList<String[]> findInString(String needle, List<String[]> haystack) {
ArrayList<String[]> found = new ArrayList<String[]>();
for(String fileLines[] : haystack) {
for(String s : fileLines) {
if(s.contains(needle)) {
found.add(fileLines);
break;
}
}
}
return found;
}
You don't need to iterate over lines twice to do what you need. You can make replacement when iterating over file.
Java 8 solution
try (BufferedReader reader = Files.newBufferedReader(Paths.get("pom.xml"))) {
reader
.lines()
.filter(x -> x.length() > 0)
.map(x -> x.trim())
.map(x -> x.replace("a", "b"))
.forEach(System.out::println);
} catch (IOException e){
//handle exception
}
Another way by using iterator
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("Naman");
list.add("Aman");
list.add("Nikhil");
list.add("Adarsh");
list.add("Shiva");
list.add("Namit");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String next = iterator.next();
if (next.startsWith("Na")) {
System.out.println(next);
}
}
}
I have a method which returns single word as a String. I need to count all those words returned by the method which reads chunk of text. Problem is I am getting the count right but output is wrong. It's repeating. Not quite sure where is things going wrong?
private int totalWords = 0;
private static Map<String, Integer> wordFrequency = new HashMap<String, Integer>();
public static void findResult(CharacterReader characterReader)
{
boolean x = true;
CharBuffer buffer = CharBuffer.allocate(100);
String str = "";
try
{
while(x)
{
char cha = characterReader.getNextChar();
Set<Character> charSet = new HashSet<Character>();
charSet.add(',');
charSet.add('.');
charSet.add(';');
charSet.add(':');
charSet.add('\'');
charSet.add('~');
charSet.add('?');
charSet.add('!');
charSet.add('%');
while(cha != ' ' && !charSet.contains(cha))
{
buffer.put(cha);
cha = characterReader.getNextChar();
}
buffer.flip();
str = buffer.toString();
buffer.clear();
countWords(str);
System.out.println(wordFrequency);
}
}catch(EOFException e)
{
x = false;
}
private static void countWords(String word)
{
if (wordFrequency.containsKey(word))
{
Integer count = wordFrequency.get(word);
count++;
wordFrequency.put(word, count);
} else {
wordFrequency.put(word, 1);
}
}
public static void main (String args[])
{
CharacterReader cr = new SimpleCharacterReader();
findResult(cr);
}
Move
System.out.println(wordFrequency);
To outside the try statement. You are printing the whole set after each word.
It's all in where you've placed your System.out.println. You've got it inside of the loop!
while(x) {
// .....
countWords(str);
System.out.println(wordFrequency);
}
Solution: do it after the loop.
while(x) {
// .....
countWords(str);
}
System.out.println(wordFrequency);
Try moving
System.out.println(wordFrequency);
out of the while loop braces...