So I've a file with these rows
155, 490, 297, 490,
-45, 19, 45, 19,
-24, 80,-12,-69, 80,
12,-92, 28,-40,
I try to read the file and find these rows which contain duplicate elements. But something with my logic is wrong and I can't find the error. Any help ?
Here is the code:
public static void main(String[] args) throws IOException {
Scanner fileInput = null;
try {
fileInput = new Scanner( new File("array_list.csv"));
String line;
while (fileInput.hasNextLine()) {
line = fileInput.nextLine();
String[] lineArr = line.split(",");
// check for missing values
boolean contains = true;
for(int i=0; i<lineArr.length; i++) {
for(int j=0; j<lineArr.length; j++) {
if(lineArr[i]==lineArr[j]) {
contains = false;
break;
}
}
if(!contains) {
// print the row .....
}
else {
contains = true;
// print some thing ...
}
}
}
} finally {
if (null != fileInput) {
fileInput.close();
}
}
}
Since you're comparing strings, you need to use the equals() method:
lineArr[i].equals(lineArr[j])
That being said, there are a few other things I can see which may cause you problems:
Be careful of spaces after commas. The sample data is inconsistent, so it's best to call lineArr[i].trim() to get rid of leading/trailing whitespace.
You should set contains to false initially and try to find a match, then set it to true and break. Then if (contains), print the row.
The way your loops are set up, you will check each element with itself. So of course you will find a duplicate for each row!
The problem that stands out to me immediately is that you are working with Strings, and you are currently using the "==" operator to compare strings on this line:
if(lineArr[i]==lineArr[j]) {
This should instead be:
if(lineArr[i].equals(lineArr[j])) {
Try replacing your code as
if(lineArr[i].equals(lineArr[j]))
instead
if(lineArr[i]==lineArr[j])
The equals() method compares the actual content of the Strings, using the underlying Unicode representation, while == compares only the identity of the objects, using their address in memory.
Put all values into a set and check if its length is equal to the original array. If so, then all values are unique, otherwise they are not:
while (fileInput.hasNextLine()) {
line = fileInput.nextLine();
List<String> lineArr = Arrays.asList(line.split(","));
if (new HashSet<String>(lineArr).size() != lineArr.size()) {
System.out.println(line);
}
}
You should compare String using equals().
Yet there are other issues in your code. At some point, i and j are equal and thus lineArr[i]==lineArr[j] will always be true.
A simple way for checking duplicates is to use a Set and check its size:
Set<String> lineSet = new HashSet<lineArr.length>;
for(String s : lineArr) {
lineSet.add(s);
}
if(lineSet.size() < lineArr.length) {
// there are duplicates
}
public static void main(String[] args) throws IOException{
Scanner fileInput = null;
try {
fileInput = new Scanner(new File("array_list.csv"));
String line;
while (fileInput.hasNextLine()) {
line = fileInput.nextLine();
String[] lineArr = line.split(",");
// check for missing values
boolean contains = true;
for(int i=0; i<lineArr.length; i++) {
for(int j=0; j<i; j++) {
if(lineArr[i].equals(lineArr[j])) {
contains = false;
break;
}
}
}
if(!contains) {
System.out.println(line);
}
else {
contains = true;
}
}
} finally {
if (null != fileInput) {
fileInput.close();
}
}
}
Here is my code for finding duplicate elements
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class StringManipulation {
public static void main(String[] args) {
StringManipulation manipulation=new StringManipulation();
manipulation.findDuplicateElementList();
//manipulation.findDuplicateElementbyMap();
}
private void findDuplicateElementList() {
String lineData = "ashish manish ashish manish sachin manish ashish neha manish";
String[] list = lineData.split(" ");
List<String> stringList = Arrays.asList(list);
// containingList=stringList;
Set<String> stringSet = new HashSet<String>();
for (int i = 0; i < stringList.size(); i++) {
int count = 0;
String currVal = stringList.get(i);
if (stringSet.contains(currVal)) {
continue;
} else {
for (String string : stringList) {
if (currVal.equals(string)) {
stringSet.add(currVal);
count++;
}
}
}
System.out.println("Occurances of " + currVal + " " + count);
}
}
}
Related
I'm trying to search of multiple words given from a user ( i used array to store them in ) from one txt file , and then if that word presented once in the file it will be displayed and if it's not it won't.
also for the words itself , if it's duplicated it will search it once.
the problem now when i search for only one it worked , but with multiple words it keeps repeated that the word isn't present even if it's there.
i would like to know where should i put the for loop and what's the possible changes.
package search;
import java.io.*;
import java.util.Scanner;
public class Read {
public static void main(String[] args) throws IOException
{
Scanner sc = new Scanner(System.in);
String[] words=null;
FileReader fr = new FileReader("java.txt");
BufferedReader br = new BufferedReader(fr);
String s;
System.out.println("Enter the number of words:");
Integer n = sc.nextInt();
String wordsArray[] = new String[n];
System.out.println("Enter words:");
for(int i=0; i<n; i++)
{
wordsArray[i]=sc.next();
}
for (int i = 0; i <n; i++) {
int count=0; //Intialize the word to zero
while((s=br.readLine())!=null) //Reading Content from the file
{
{
words=s.split(" "); //Split the word using space
for (String word : words)
{
if (word.equals(wordsArray[i])) //Search for the given word
{
count++; //If Present increase the count by one
}
}
if(count == 1)
{
System.out.println(wordsArray[i] + " is unique in file ");
}
else if (count == 0)
{
System.out.println("The given word is not present in the file");
}
else
{
System.out.println("The given word is present in the file more than 1 time");
}
}
}
}
fr.close();
}
}
The code which you wrote is error prone and remember always there should be proper break condition when you use while loop.
Try the following code:
public class Read {
public static void main(String[] args)
{
// Declaring the String
String paragraph = "These words can be searched";
// Declaring a HashMap of <String, Integer>
Map<String, Integer> hashMap = new HashMap<>();
// Splitting the words of string
// and storing them in the array.
String[] words = new String[]{"These", "can", "searched"};
for (String word : words) {
// Asking whether the HashMap contains the
// key or not. Will return null if not.
Integer integer = hashMap.get(word);
if (integer == null)
// Storing the word as key and its
// occurrence as value in the HashMap.
hashMap.put(word, 1);
else {
// Incrementing the value if the word
// is already present in the HashMap.
hashMap.put(word, integer + 1);
}
}
System.out.println(hashMap);
}
}
I've tried by hard coding the values, you can take words and paragraph from the file and console.
The 'proper' class to use for extracting words from text is java.text.BreakIterator
You can try the following (reading line-wise in case of large files)
import java.text.BreakIterator;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
import java.nio.file.Files;
import java.nio.file.Paths;
public class WordFinder {
public static void main(String[] args) {
try {
if (args.length < 2) {
WordFinder.usage();
System.exit(1);
}
ArrayList<String> argv = new ArrayList<>(Arrays.asList(args));
String path = argv.remove(0);
List<String> found = WordFinder.findWords(Files.lines(Paths.get(path)), argv);
System.out.printf("Found the following word(s) in file at %s%n", path);
System.out.println(found);
} catch (Throwable t) {
t.printStackTrace();
}
}
public static List<String> findWords(Stream<String> lines, ArrayList<String> searchWords) {
List<String> result = new ArrayList<>();
BreakIterator boundary = BreakIterator.getWordInstance();
lines.forEach(line -> {
boundary.setText(line);
int start = boundary.first();
for (int end = boundary.next(); end != BreakIterator.DONE; start = end, end = boundary.next()) {
String candidate = line.substring(start, end);
if (searchWords.contains(candidate)) {
result.add(candidate);
searchWords.remove(candidate);
}
}
});
return result;
}
private static void usage() {
System.err.println("Usage: java WordFinder <Path to input file> <Word 1> [<Word 2> <Word 3>...]");
}
}
Sample run:
goose#t410:/tmp$ echo 'the quick brown fox jumps over the lazy dog' >quick.txt
goose#t410:/tmp$ java WordFinder quick.txt dog goose the did quick over
Found the following word(s) in file at quick.txt
[the, quick, over, dog]
goose#t410:/tmp$
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.
Disclaimer : I'm using this Post, as reference for List<Object> to List<String> and this Post for Java List<String> of strings to a JavaScript array.
I've List<Seat> and I want to get all values of it in a comma separated String, I tried in this way
import java.util.*;
import java.lang.*;
class Rextester
{
public Rextester(){
Seat seat1 = new Seat();
seat1.setSeatNumber(1);
Seat seat2 = new Seat();
seat2.setSeatNumber(2);
Seat seat3 = new Seat();
seat3.setSeatNumber(3);
List<Seat> seatList = new ArrayList<Seat>();
seatList.add(seat1);
seatList.add(seat2);
seatList.add(seat3);
Utility util = new Utility();
String stringSeats = util.toJavascriptArray(seatList);
System.out.println("JavaScriptArray is " + stringSeats);
}
public static void main(String args[])
{
new Rextester();
}
private class Seat {
private Integer seatNumber;
public Integer getSeatNumber() {
return this.seatNumber;
}
public void setSeatNumber(Integer seatNumber) {
this.seatNumber = seatNumber;
}
public String toString() {
return ""+ seatNumber;
}
}
private class Utility {
public String toJavascriptArray(List<Seat> listSeats){
List<String> strings = new ArrayList<String>();
for (Seat object : listSeats) {
strings.add(object != null ? object.toString() : null);
}
String[] arr = new String[strings.size()];
arr = strings.toArray(arr);
StringBuffer sb = new StringBuffer();
sb.append("[");
for(int i=0; i<arr.length; i++){
if(i+1 < arr.length){
sb.append(",");
}
}
sb.append("]");
return sb.toString();
}
}
}
but this gives me
JavaScriptArray is [,,]
on console, am I making some mistakes? an online working code is http://rextester.com/NDUGT61105
You didn't append iterated element, see below
for (int i = 0; i < arr.length; i++) {
sb.append(arr[i]); // add this
if (i + 1 < arr.length) {
sb.append(",");
}
}
have a look at the toString implementations of Arrays and List
Simply you can return
strings.toString()
or
Arrays.toString(arr)
To get the expected result
Another option, if you're using Java 8 is using StringJoiner:
https://docs.oracle.com/javase/8/docs/api/java/util/StringJoiner.html
You forgot to append the array elements to the string buffer!
Add
sb.append(arr[i]);
inside the loop where you prepare the string buffer and everything is ok
What I'm trying to do is add numbers from a .txt file and split it by ; into my ArrayList listR2. As of now it semi works, however the result is that only the last 2 persons score is added, the first persons score is just getting null.
Is it some problem with my split?
Any ideas how i get the program to write all the scores?
It is skipping lines (from your file) in your code because you have used
for (int i = 3; i < itemStudent.length; i++) {
String test = studin.readLine(); //<--- this is the error
listR2.add(test);
}
Instead use
String test = itemStudent[i]; // to add the scores into the listR2
First, your code:
BufferedReader studin = new BufferedReader(new FileReader(studentFile));
grader.Student student;
student = new Student();
String line, eNamn, fNamn, eMail;
ArrayList<String> listR = new ArrayList<String>();
ArrayList<String> listR2 = new ArrayList<String>();
//loop for the file and setters for first, lastname and email
while ((line = studin.readLine()) != null) {
if (line.contains(";")) {
//# you don't need regex to split on a single specific character
String[] itemStudent = line.split("[;]");
eNamn = itemStudent[0];
fNamn = itemStudent[1];
eMail = itemStudent[2];
//#why are you using the Student object if you never use it in any way ?
//#also you are always updating the same "Student". if you expect to add it to say an ArrayList,
//#you need to declare a new student at the beginning of the loop (not outside of it)
student.setFirstName(fNamn);
student.setLastName(eNamn);
student.setEmail(eMail);
//Loop for the sum of the tests
Integer sum = 0; //# why Interger, the "int" primitive is more than sufficient
for (int index = 3; index < itemStudent.length; index++) {
try {
sum += Integer.parseInt(itemStudent[index]);
listR.add(itemStudent[index]);
} catch (Exception ex) {} //very bad practice, nerver silently drop exceptions.
}
//# that part is just wrong in many ways, I guess it's some left over debug/testing code
//# this also makes you skip lines as you will read as many lines as you have elements (minus 3) in itemStudent
/*
for (int i = 3; i < itemStudent.length; i++) {
String test = studin.readLine();
listR2.add(test);
}
*/
System.out.println(eNamn + " " + fNamn + " " + eMail + " SUMMA:" + sum + " " );
//# you'll get a nice pointer address, but not it's values, you need to itterate the list to view it's content
System.out.println(listR2);
}
}
The //# mark my comments
and here a quick example displaying the object approach:
(may contains misspells/missing imports but otherwise should be fine the compiler should will you). to run it:
java Main "your_file"
import java.util.ArrayList;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
class Student{
String fname;
String lname;
String mail;
int sum;
Student(String fn,String ln,String ml){
fname=fn;
lname=ln;
mail=ml;
sum=0;
}
void addScore(int n){
sum += n;
}
public String toString() {
return "Student: "+fname+" "+lname+", "+mail+" sum: "+sum;
}
}
try {
BufferedReader br = new BufferedReader(new FileReader(args[0]));
ArrayList<Student> stdnts = new ArrayList<Student>();
String line = br.readLine();
while (line != null) {
if (line.contains(";")) {
String[] stdnt_arr = line.split(";");
Student stdnt = new Student(stdnt_arr[0],stdnt_arr[1],stdnt_arr[2]);
for (int i = 3;i<stdnt_arr.length;i++){
try {
stdnt.addScore(Integer.parseInt(stdnt_arr[i]));
} catch (NumberFormatException e) {
//not a number
e.printStackTrace();
}
}
stdnts.add(stdnt);
System.out.println(stdnt.toString());
}
line = br.readLine();
}
} catch(IOException e){
//things went wrong reading the file
e.printStackTrace();
}
}
}
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);
}
}
}