Reading file into HashMap - java

I am reading a file with the city and its population.
the file looks like this:
New York city
NY 8,175,133
Los Angeles city
CA 3,792,621
............
The format of the original file is different but I can't modify my code to read it properly. The original file looks like this:
New York city NY 8,175,133
Los Angeles city CA 3,792,621
...........
I posted the code (below) that works for the first version, but how can I make it to work for the original format? I am trying to make the city my key and the state & population as the value.
I know it's something simple but I can't figure out what it is.
public static void main(String[] args) throws FileNotFoundException
{
File file = new File("test.txt");
Scanner reader = new Scanner(file);
HashMap<String, String> data = new HashMap<String, String>();
while (reader.hasNext())
{
String city = reader.nextLine();
String state_pop = reader.nextLine();
data.put(city, state_pop);
}
Iterator<String> keySetIterator = data.keySet().iterator();
while (keySetIterator.hasNext())
{
String key = keySetIterator.next();
System.out.println(key + "" + data.get(key));
}
}
Thank you.

Just replace your code where you call readLine with something like this:
String line = scannner.readLine();
int space = line.lastIndexOf(' ', line.lastIndexOf(' ') - 1);
String city = line.substring(0,space);
String statepop = line.substring(space+1);
then put your city and statepop into your map.
Basically, this code finds the second last space and splits your String there.

Perhaps something like:
while (reader.hasNext())
{
String line = reader.nextLine();
int splitIndex = line.lastIndexOf(" city ");
data.put(line.substring(0, splitIndex + 5), line.substring(splitIndex + 6));
}

Related

How to print a substring with only the matching elements of a string?

Given a String that lists metadata about a book line by line, how do I print out only the lines that match the data I am looking for?
In order to do this, I've been trying to create substrings for each lines using indexes. The substring starts at the beginning of a line and ends before a "\n". I have not seen lists, arrays or bufferedReader yet.
For each substring that I parse through, I check if it contains my pattern. If it does, I add it to a string that only includes my results.
Here would be an example of my list (in french); I'd like to match, for say, all the books written in 2017.
Origine D. Brown 2017 Thriller Policier
Romance et de si belles fiancailles M. H. Clark 2018 thriller policier Romance
La fille du train P. Hawkins 2015 Policier
There is a flaw in how I am doing this and I am stuck with an IndexOutOfBounds exception that I can't figure out. Definitely new in creating algorithms like this.
public static String search() {
String list;
int indexLineStart = 0;
int indexLineEnd = list.indexOf("\n");
int indexFinal = list.length()-1;
String listToPrint = "";
while (indexLineStart <= indexFinal){
String listCheck = list.substring(indexLineStart, indexLineEnd);
if (listCheck.contains(dataToMatch)){
listToPrint = listToPrint + "\n" + listCheck;
}
indexLineStart = indexLineEnd +1 ;
indexLineEnd = list.indexOf("\n", indexLineStart);
}
return listeToPrint;
}
Regardless of the comments about using split() and String[], which do have merit :-)
The IndexOutOfBounds exception I believe is being caused by the second of these two lines:
indexLineStart = indexLineEnd +1 ;
indexLineEnd = list.indexOf("\n", indexLineStart);
You wan't them swapped around (I believe).
You don't have to make this much complex logic by using String.substring(), what you can use is String.split() and can make an array of your string. At each index is a book, then, you can search for you matching criteria, and add the book to the finalString if it matches your search.
Working Code:
public class stackString
{
public static void main(String[] args)
{
String list = "Origine D. Brown 2017 Thriller Policier\n Romance et de si belles fiancailles M. H. Clark 2018 thriller policier Romance\n La fille du train P. Hawkins 2015 Policier\n";
String[] listArray = list.split("\n"); // make a String Array on each index is new book
String finalString = ""; // final array to store the books that matches the search
String matchCondition = "2017";
for(int i =0; i<listArray.length;i++)
if(listArray[i].contains(matchCondition))
finalString += listArray[i]+"\n";
System.out.println(finalString);
}
}
Here is a solution using pattern matching
public static List<String> search(String input, String keyword)
{
Pattern pattern = Pattern.compile(".*" + keyword + ".*");
Matcher matcher = pattern.matcher(input);
List<String> linesContainingKeyword = new LinkedList<>();
while (matcher.find())
{
linesContainingKeyword.add(matcher.group());
}
return linesContainingKeyword;
}
Since I wasn't allowed to use lists and arrays, I got this to be functional this morning.
public static String linesWithPattern (String pattern){
String library;
library = library + "\n"; //Added and end of line at the end of the file to parse through it without problem.
String substring = "";
String substringWithPattern = "";
char endOfLine = '\n';
int nbrLines = countNbrLines(library, endOfLine); //Method to count number of '\n'
int lineStart = 0;
int lineEnd = 0;
for (int i = 0; i < nbrLines ; i++){
lineStart = lineEnd;
if (lineStart == 0){
lineEnd = library.indexOf('\n');
} else if (lineStart != 0){
lineEnd = library.indexOf('\n', (lineEnd + 1));
}
substring = library.substring(lineStart, lineEnd);
if (substring.toLowerCase().contains(motif.toLowerCase())){
substringWithPattern = substring + substringWithPattern + '\n';
}
if (!library.toLowerCase().contains(pattern.toLowerCase())){
substringWithPattern = "\nNO ENTRY FOUND \n";
}
}
if (library.toLowerCase().contains(pattern)){
substringWithPattern = "This or these books were found in the library \n" +
"--------------------------" + substringWithPattern;
}
return substringWithPattern;
The IndexOutOfBounds exception is thrown when the index you are searching for is not in the range of array length. When I went through the code, you are getting this exception because of below line execution where probably the indexLineEnd value is more than the actual length of List if the string variable list is not Null (Since your code doesn't show list variable to be initialized).
String listCheck = list.substring(indexLineStart, indexLineEnd);
Please run the application in debug mode to get the exact value that is getting passed to the method to understand why it throwing the exception.
you need to be careful at calculating the value of indexLineEnd.

reading student record from file

I'm trying to read a file that has student record(first name, last name, and grade).
I have written a simple code to accomplish this task but the code fails after reading two lines from the text file. Here is my code:
public class Student {
private final String first,last;
final int MAXGRADE = 100;
final int LOWGRADE = 0;
private final int grade;
public Student(String firstname,String lastname, int grade){
this.first = firstname;
this.last = lastname;
this.grade = grade;
}
#Override
public String toString(){
return first + " " + last + "\t" + grade;
}
}
and the driver has this code
public class driver {
public static void main(String[] args) throws FileNotFoundException {
String first_name ,last_name;
int grade;
Scanner fileInput = new Scanner(new File("data1.txt"));
while (fileInput.hasNextLine())
{
first_name = fileInput.next();
last_name = fileInput.next();
grade = fileInput.nextInt();
Student st = new Student(first_name, last_name,grade);
System.out.println(st);
}
}
}
the compiler is pointing to this
grade = fileInput.nextInt();
as the source of the error.
This code is working for me. Make Sure
The location of text file correctly given,
Integer value given at 3rd position in each line (like:- steve smith 22)
If you are using Java 8, then functional way of doing this would be:
String filePath = "C:/downloads/stud_records.txt"; // your file path
/*
* Gives you a list of all students form the file
*/
List<Student> allStudentsFromFile = Files.lines(Paths.get(filePath)).map(line -> {
String[] data = line.split("\\s+"); //Split on your delimiter
Student stud = new Student(data[0], data[1], Integer.parseInt(data[2]));
return stud;
}).collect(Collectors.toList());
Note: I've made an assumption that this:
FirstName LastName Grade
is the input file format.
From the comment you post "#AxelH each line represents a single student first, last name and grade" we can see the problem.
Your actual loop to read a line
while (fileInput.hasNextLine())
{
first_name = fileInput.next();
last_name = fileInput.next();
grade = fileInput.nextInt();
Student st = new Student(first_name, last_name,grade);
System.out.println(st);
}
Is reading 3 lines, one per fileInput.nextXXX();. What you need to do is
Read a line as a String : `String line = fileInput.nextLine();
Split that line base on the delimiter : `String[] data = line.split(" "); //Or your delimiter if not space (carefull with some names...)
Set the value from this array (parse are need for integer)
EDIT :
I have made a mistake since I am used to use nextline and not next, I can't delete the answer as it is accepted so I will update it to be more correct without changing the content.
The code is indeed correct, next will take the following input until the next delimiter, \\p{}javaWhitespace}+, but using the given solution would give you more solution to manage composed names as it could be Katrina Del Rio 3.

How to remove matched words from end of String

I want to remove the following words from end of String ‘PTE’, ‘LTD’, ‘PRIVATE’ and ‘LIMITED’
i tried the code but then i stuck. i tried this
String[] str = {"PTE", "LTD", "PRIVATE", "LIMITED"};
String company = "Basit LTD";
for(int i=0;i<str.length;i++) {
if (company.endsWith(str[i])) {
int position = company.lastIndexOf(str[i]);
company = company.substring(0, position);
}
}
System.out.println(company.replaceAll("\\s",""));
It worked. But suppose the company is Basit LIMITED PRIVATE LTD PTE or Basit LIMITED PRIVATE PTE LTD or any combination of four words in the end. Then the above code just remove the last name i.e., PTE or PRIVATE and so on, and the output is BasitLIMITEDPRIVATELTD.
I want output to be just Basit
How can i do it?
Thanks
---------------Edit---
Please note here the company name is just an example, it is not necessary that it is always the same. may be i have name like
String company = "Masood LIMITED LTD PTE PRIVATE"
or any name that can have the above mentioned words at the end.
Thanks
You can do this in single line. no need to loop through. just use String#replaceAll(regex, str).
company = company.replaceAll("PTE$*?|LTD$*?|PRIVATE$*?|LIMITED$*?","");
If you place the unwanted words in the map it will be ommitted in the resultant string
HashMap map = new HashMap();
map.put("PTE", "");
map.put("LTD", "");
map.put("PRIVATE", "");
map.put("LIMITED", "");
String company = "Basit LTD PRIVATE PTE";
String words[] = company.split(" ");
String resultantStr = "";
for(int k = 0; k < words.length; k++){
if(map.get(words[k]) == null) {
resultantStr += words[k] + " ";
}
}
resultantStr = resultantStr.trim();
System.out.println(" Trimmed String: "+ resultantStr);
If you want to remove these suffixes only at the end of the string, then you could introduce a while loop:
String[] str = {"PTE", "LTD", "PRIVATE", "LIMITED"};
boolean foundSuffix = true;
String company = "Basit LTD";
while (foundSuffix) {
foundSuffix = false;
for(int i=0;i<str.length;i++) {
if (company.endsWith(str[i])) {
foundSuffix = true;
int position = company.lastIndexOf(str[i]);
company = company.substring(0, position);
}
}
}
System.out.println(company.replaceAll("\\s",""));
If you don't mind transforming PTE Basit LIMITED INC to Basit (and also remove the first PTE), then replaceAll should work, as explained by others.
I was trying to do exactly same thing for one of my projects. I wrote this code few days earlier. Now I was exactly trying to find a much better way to do it, that's how I found this Question. But after seeing other answers I decided to share my version of the code.
Collection<String> stopWordSet = Arrays.asList("PTE", "LTD", "PRIVATE", "LIMITED");
String company = "Basit LTD"; //Or Anything
String[] tokens = company.split("[\#\]\\\_\^\[\"\#\ \!\&\'\`\$\%\*\+\(\)\.\/\,\-\;\~\:\}\|\{\?\>\=\<]+");
Stack<String> tokenStack = new Stack<>();
tokenStack.addAll(Arrays.asList(tokens));
while (!tokenStack.isEmpty()) {
String token = tokenStack.peek();
if (stopWordSet.contains(token))
tokenStack.pop();
else
break;
}
String formattedCompanyName = StringUtils.join(tokenStack.toArray());
Try this :
public static void main(String a[]) {
String[] str = {"PTE", "LTD", "PRIVATE", "LIMITED"};
String company = "Basit LIMITED PRIVATE LTD PTE";
for(int i=0;i<str.length;i++) {
company = company.replaceAll(str[i], "");
}
System.out.println(company.replaceAll("\\s",""));
}
All you need is to use trim() and call your function recursively, Or each time you remove a sub string from the end, reset your i to 0.
public class StringMatchRemove {
public static void main(String[] args) {
String str="my name is noorus khan";
String search="noorus";
String newString="";
String word=str.replace(search," ");
StringTokenizer st = new StringTokenizer(word," ");
while(st.hasMoreTokens())
{
newString = newString + st.nextToken() + " ";
}
System.out.println(newString);
}
first using the replace method we get word=my name is ..... khan (Note: here(.) represents the space). Now we should have to remove these spaces for that we are creating a new string adding all the token simply.
Output: my name is khan

Java Scanner Class useDelimiter Method

I have to read from a text file containing all the NCAA Division 1 championship games since 1933,
the file is in this format: 1939:Villanova:42:Brown:30
1945:New York University:70:Ohio State:65 **The fact that some Universities have multiple white spaces is giving me lots of trouble beause we are only to read the school names and discard the year, points and colon. I do not know if I have to use a delimiter that discards what spaces, but buttom line is I am a very lost.
We are to discard the date, points, and ":". I am slightly fimilar with the useDelimiter method but, I have read that a .split("") might be useful. I am having a great deal of problems due to my lack of knowledge in patterns.
THIS IS WHAT I HAVE SO FAR:
class NCAATeamTester
{
public static void main(String[]args)throws IOException
{
NCAATeamList myList = new NCAATeamList(); //ArrayList containing teams
Scanner in = new Scanner(new File("ncaa2012.data"));
in.useDelimiter("[A-Za-z]+"); //String Delimeter excluding non alphabetic chars or ints
while(in.hasNextLine()){
String line = in.nextLine();
String name = in.next(line);
String losingTeam = in.next(line);
//Creating team object with winning team
NCAATeamStats win = new NCAATeamStats(name);
myList.addToList(win); //Adds to List
//Creating team object with losing team
NCAATeamStats lose = new NCAATeamStats(losingTeam);
myList.addToList(lose)
}
}
}
What about
String[] spl = line.split(':');
String name1 = spl[1];
String name2 = spl[3];
?
Or, if there are more records at the same line, use regular expressions :
String line = "1939:Villanova:42:Brown:30 1945:New York University:70:Ohio State:65";
Pattern p = Pattern.compile("(.*?:){4}[0-9]+");
Matcher m = p.matcher(line);
while (m.find())
{
String[] spl = m.group().split(':');
String name = spl[1];
String name2 = spl[3];
}

string tokenizer stopping after first line

I have a text file I am trying to break up with string tokenizer. Here is a few lines of the text file:
Mary Smith 1
James Johnson 2
Patricia Williams 3
I am trying to break up into first name, last name and Customer ID.
I have so far been able to do that but it stops after mary smith.
Here is my code:
public static void createCustomerList(BufferedReader infileCust,
CustomerList customerList) throws IOException
{
String firstName;
String lastName;
int custId;
//take first line of strings before breaking them up to first last and cust ID
String StringToBreak = infileCust.readLine();
//split up the string with string tokenizer
StringTokenizer st = new StringTokenizer(StringToBreak);
firstName = st.nextToken();
while(st.hasMoreElements())
{
lastName = st.nextToken();
custId = Integer.parseInt(st.nextToken());
CustomerElement CustomerObject = new CustomerElement();
CustomerObject.setCustInfo(firstName,lastName,custId);
customerList.addToList(CustomerObject);
}
}
String StringToBreak = infileCust.readLine();
reads the FIRST line from the file. And you feed the StringTokenizer with it. It's normal that StringTokenized doesn't find more tokens.
You have to create a second loop enclosing all this to read every line. It is:
outer loop: readLine until it gets null {
create a StringTokenizer that consumes *current* line
inner loop: nextToken until !hasMoreElements()
}
Well, indeed you don't need to do an inner loop because you have three different fields. It's enough with:
name = st.nextToken();
lastName = st.nextToken();
id = st.nextToken;
For the outer loop, you need to store the contents of the current line in the stringToBreak variable so that you can access it inside the loop.
You need a new StringTokenizer for each line so it needs to be inside the loop.
String stringToBreak = null;
while ((stringToBreak = infileCust.readLine()) != null) {
//split up the string with string tokenizer
StringTokenizer st = new StringTokenizer(stringToBreak);
firstName = st.nextToken();
lastName = st.nextToken();
custId = Integer.parseInt(st.nextToken());
}
First off, you want to look at your loop, specifically how you have firstName outside of the loop so that is going to throw all of you tokens off. You will be trying to create new customer objects without enough information.

Categories

Resources