Find any key from a hashmap in a file using java 8 - java

I want to find a key(to be taken from hashmap) in a file using java 8. If any key is found in the file it should print true. Below is my code
public static void main(String[] args) {
String fileName = "C:\\Users\\ABC\\Desktop\\Paper_R2_Final.txt";
Map<String, String> myMap = new HashMap<String,String>();
myMap.put("ecological", "myFirstKey");
myMap.put("Survey", "mySecondKey");
myMap.put("Worth", "myThirdKey");
//read file into stream, try-with-resources
try (Stream<String> stream = Files.lines(Paths.get(fileName),StandardCharsets.ISO_8859_1)) {
myMap.forEach((k,v)->System.out.println("key: " + k + ", value: " + v));
//Problem in the below line
System.out.println(stream.anyMatch(line->line.contains((CharSequence) myMap.keySet())));
} catch (IOException e) {
e.printStackTrace();
}
}

Try this:
public static void main(String[] args) {
String fileName = "C:\\Users\\ABC\\Desktop\\Paper_R2_Final.txt";
Map<String, String> myMap = new HashMap<String,String>();
myMap.put("ecological", "myFirstKey");
myMap.put("Survey", "mySecondKey");
myMap.put("Worth", "myThirdKey");
List<String> myList = new ArrayList<String>(myMap.keySet());
//if the line contains any of the keys
Predicate<String> p = (str) -> myList.stream().anyMatch(key -> str.contains(key));
//read file into stream, try-with-resources
try (Stream<String> stream = Files.lines(Paths.get(fileName),StandardCharsets.ISO_8859_1)) {
boolean foundAKey = stream.anyMatch(p);
if(foundAKey) {
//a key is found
}
} catch (IOException e) {
e.printStackTrace();
}
}

myMap.keySet() is giving you a Set, which is a collection. Casting it to a CharSequence makes no sense and will not give you what you are expecting.
One way of doing what you want would be to tokenize your line (for example split on the spaces), and check if your keySet contains the tokens one by one.
Some pseudo java code :
keySet = myMap.keySet();
for each line in the file {
tokens = line.split(" ");
for each token in tokens {
if keySet.contains(token) {
// Do whatever you want
}
}
}

Try this:
Files.lines(Paths.get(fileName), StandardCharsets.ISO_8859_1)
.anyMatch(line -> myMap.keySet().stream().anyMatch(line::contains));

Related

Scanning integer and string from file in Java

I'm new to Java and I have to read from a file, and then convert what I have read into variables. My file consists of a fruit, then a price and it has a long list of this. The file looks like this:
Bananas,4
Apples,5
Strawberry,8
...
Kiwi,3
So far I have created two variables(double price and String name), then set up a scanner that reads from the file.
public void read_file(){
try{
fruits = new Scanner(new File("fruits.txt"));
print_file();
}
catch(Exception e){
System.out.printf("Could not find file\n");
}
}
public void print_file(){
while(fruits.hasNextLine()){
String a = fruits.nextLine();
System.out.printf("%s\n", a);
return;
}
}
Currently I am only able to print out the entire line. But I was wondering how I could break this up to be able to store the lines into variables.
So your string a has an entire line like Apples,5. So try to split it by comma and store it into variables.
String arr[] = a.split(",");
String name = arr[0];
int number = Integer.parseInt(arr[1]);
Or if prices are not integers, then,
double number = Double.parseDouble(arr[1]);
Using java 8 stream and improved file reading capabilities you can do it as follows. it stores item and count as key value pair in a map. It is easy to access by key afterwards.
I know this Maybe too advance but eventually this will help you later when getting to know new stuff in java.
try (Stream<String> stream = Files.lines(Paths.get("src/test/resources/items.txt"))) {
Map<String, Integer> itemMap = stream.map(s -> s.split(","))
.collect(toMap(a -> a[0], a -> Integer.valueOf(a[1])));
System.out.println(itemMap);
} catch (IOException e) {
e.printStackTrace();
}
output
{Apples=5, Kiwi=3, Bananas=4, Strawberry=8}
You can specify a delimiter for the scanner by calling the useDelimiter method, like:
public static void main(String[] args) {
String str = "Bananas,4\n" + "Apples,5\n" + "Strawberry,8\n";
try (Scanner sc = new Scanner(str).useDelimiter(",|\n")) {
while (sc.hasNext()) {
String fruit = sc.next();
int price = sc.nextInt();
System.out.printf("%s,%d\n", fruit, price);
}
} catch (Exception e) {
e.printStackTrace(System.out);
}
}
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Test {
public static void main(String[] args) {
BufferedReader reader;
try {
reader = new BufferedReader(new FileReader(
"C://Test/myfile.txt")); //Your file location
String line = reader.readLine(); //reading the line
while(line!=null){
if(line!=null && line.contains(",")){
String[] data = line.split(",");
System.out.println("Fruit:: "+data[0]+" Count:: "+Integer.parseInt(data[1]));
}
//going over to next line
line = reader.readLine();
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

Merge two array list into a TreeMap in java

I want to combine these two text files
Driver details text file:
AB11; Angela
AB22; Beatrice
Journeys text file:
AB22,Edinburgh ,6
AB11,Thunderdome,1
AB11,Station,5
And I want my output to be only the names and where the person has been. It should look like this:
Angela
Thunderdone
Station
Beatrice
Edinburgh
Here is my code. I'm not sure what i'm doing wrong but i'm not getting the right output.
ArrayList<String> names = new ArrayList<String>();
TreeSet<String> destinations = new TreeSet<String>();
public TaxiReader() {
BufferedReader brName = null;
BufferedReader brDest = null;
try {
// Have the buffered readers start to read the text files
brName = new BufferedReader(new FileReader("taxi_details.txt"));
brDest = new BufferedReader(new FileReader("2017_journeys.txt"));
String line = brName.readLine();
String lines = brDest.readLine();
while (line != null && lines != null ){
// The input lines are split on the basis of certain characters that the text files use to split up the fields within them
String name [] = line.split(";");
String destination [] = lines.split(",");
// Add names and destinations to the different arraylists
String x = new String(name[1]);
//names.add(x);
String y = new String (destination[1]);
destinations.add(y);
// add arraylists to treemap
TreeMap <String, TreeSet<String>> taxiDetails = new TreeMap <String, TreeSet<String>> ();
taxiDetails.put(x, destinations);
System.out.println(taxiDetails);
// Reads the next line of the text files
line = brName.readLine();
lines = brDest.readLine();
}
// Catch blocks exist here to catch every potential error
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
// Finally block exists to close the files and handle any potential exceptions that can happen as a result
} finally {
try {
if (brName != null)
brName.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
public static void main (String [] args){
TaxiReader reader = new TaxiReader();
}
You are reading 2 files in parallel, I don't think that's gonna work too well. Try reading one file at a time.
Also you might want to rethink your data structures.
The first file relates a key "AB11" to a value "Angela". A map is better than an arraylist:
Map<String, String> names = new HashMap<String, String>();
String key = line.split(",")[0]; // "AB11"
String value = line.split(",")[1]; // "Angela"
names.put(key, value)
names.get("AB11"); // "Angela"
Similarly, the second file relates a key "AB11" to multiple values "Thunderdome", "Station". You could also use a map for this:
Map<String, List<String>> destinations = new HashMap<String, List<String>>();
String key = line.split(",")[0]; // "AB11"
String value = line.split(",")[1]; // "Station"
if(map.get(key) == null) {
List<String> values = new LinkedList<String>();
values.add(value);
map.put(key, values);
} else {
// we already have a destination value stored for this key
// add a new destination to the list
List<String> values = map.get(key);
values.add(value);
}
To get the output you want:
// for each entry in the names map
for(Map.Entry<String, String> entry : names.entrySet()) {
String key = entry.getKey();
String name = entry.getValue();
// print the name
System.out.println(name);
// use the key to retrieve the list of destinations for this name
List<String> values = destinations.get(key);
for(String destination : values) {
// print each destination with a small indentation
System.out.println(" " + destination);
}
}

HashMap String and Count number of times each word is used

The question below is in Java
Sample data : https://tartarus.org/martin/PorterStemmer/output.txt
I have a tokenizationString String array that contain words that similar to the list above with many duplicated words.
I have to conver that string array into a hashmap and then use the hashmap to count the number of times each word is used (count the duplicated value in the string array but i have to use hashmap related method) .
I am thinking of doing in this way
Map<Integer, String> hashMap = new HashMap<Integer, String>();
for(int i = 0 ; i < tokenizationString.length; i++)
{
hashMap.put(i, tokenizationString[i]);
}
After that I will have to sort the string array by # of time they are used.
In the end I want to be able to print out the result like:
the "was used" 502 "times"
i "was used" 50342 "times"
apple "was used" 50 "times"
Firstly, your map should be like Map<String, Integer>(string and its frequency).
I am giving you the Java 8 stream solution.
public static void main(String[] args) {
try (Stream<String> lines = Files.lines(Paths.get("out.txt"))) {
Map<String, Long> frequency = lines
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(o, n) -> o,
LinkedHashMap::new
));
} catch (IOException e) {
e.printStackTrace();
}
}
Above code will read from file line by line. Then collect as a frequency map. Then again convert them into stream of entrySet. Then sort the stream based on the value in reverse order. Lastly collect them as a LinkedHashMap. LinkedHashMap because it will maintain the insersion order. Take look at Java 8 Stream API.
Instead of
hashMap.put(i, tokenizationString[i]);
first check if the word is already present, and then increment the corresponding entry:
int count = hashMap.containsKey(tokenizationString[i]) ? hashMap.get(tokenizationString[i]) : 0;
hashMap.put(tokenizationString[i], count + 1);
you can achieve this by Google Gauva library's MultiMap class as below. Also find the working example at this link - https://gist.github.com/dkalawadia/8d06fba1c2c87dd94ab3e803dff619b0
FileInputStream fstream = null;
BufferedReader br = null;
try {
fstream = new FileInputStream("C:\\temp\\output.txt");
br = new BufferedReader(new InputStreamReader(fstream));
String strLine;
Multimap<String, String> multimap = ArrayListMultimap.create();
// Read File Line By Line
while ((strLine = br.readLine()) != null) {
multimap.put(strLine, strLine);
}
for (String key : multimap.keySet()) {
System.out.println(key + "was used " + multimap.get(key).size() + "times");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fstream != null) {
fstream.close();
}
if(br!=null){
br.close();
}
}

Convert CSV values to a HashMap key value pairs in JAVA

HI I have a csv called test.csv . I am trying to read the csv line by line and convert the values into a hash key value pairs .
Here is the code :-
public class Example {
public static void main(String[] args) throws ParseException, IOException {
// TODO Auto-generated method stub
BufferedReader br = new BufferedReader(new FileReader("test.csv"));
String line = null;
HashMap<String,String> map = new HashMap<String, String>();
while((line=br.readLine())!=null){
String str[] = line.split(",");
for(int i=0;i<str.length;i++){
String arr[] = str[i].split(":");
map.put(arr[0], arr[1]);
}
}
System.out.println(map);
}
}
The csv file is as follows :-
1,"testCaseName":"ACLTest","group":"All_Int","projectType":"GEN","vtName":"NEW_VT","status":"ACTIVE","canOrder":"Yes","expectedResult":"duplicateacltrue"
2,"testCaseName":"DCLAddTest","group":"India_Int","projectType":"GEN_NEW","vtName":"OLD_VT","status":"ACTIVE","canOrder":"Yes","expectedResult":"invalidfeaturesacltrue"
When I run this code I get this error :-
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
Example.main(Example.java:33)
Can anyone please help me to fix the code and find out the error in my program ?
Using FasterXML's CSV package:
https://github.com/FasterXML/jackson-dataformats-text/tree/master/csv
public static List<Map<String, String>> read(File file) throws JsonProcessingException, IOException {
List<Map<String, String>> response = new LinkedList<Map<String, String>>();
CsvMapper mapper = new CsvMapper();
CsvSchema schema = CsvSchema.emptySchema().withHeader();
MappingIterator<Map<String, String>> iterator = mapper.reader(Map.class)
.with(schema)
.readValues(file);
while (iterator.hasNext()) {
response.add(iterator.next());
}
return response;
}
In your String when you split it on first time only contains arr[0] as 1 nothing in arr[1] so it will cause an Exception
If you does not need the 1,2, etc.. You can look the following code:
String str[] = line.split(",");
for(int i=1;i<str.length;i++){
String arr[] = str[i].split(":");
map.put(arr[0], arr[1]);
}
The problem is that when you split your str, the first element in each line is alone (i.e 1 and 2). So arr only contains ["1"], and hence arr[1] doesn't exists.
I.e for the example input :
1,"testCaseName":"ACLTest"
split by , => str contains {1, testCaseName:ACLTest}
split by : at the first iteration => arr contains {1}
Example :
String s = "1,testCaseName:ACLTest";
String str[] = s.split(",");
System.out.println(Arrays.toString(str));
for(String p : str){
String arr[] = p.split(":");
System.out.println(Arrays.toString(arr));
}
Output :
[1, testCaseName:ACLTest]
[1] //<- here arr[1] doesn't exists, you only have arr[0] and hence the ArrayIndexOutOfBoundsException when trying to access arr[1]
[testCaseName, ACLTest]
To fix your code (if you don't want to use a CSV parser), make your loop starting at 1 :
for(int i=1;i<str.length;i++){
String arr[] = str[i].split(":");
map.put(arr[0], arr[1]);
}
Another problem is that the HashMap use the hashCode of the keys to store the (key, value) pairs.
So when insering "testCaseName":"ACLTest" and "testCaseName":"DCLAddTest", the first value will be erased and replace by the second one :
Map<String, String> map = new HashMap<>();
map.put("testCaseName","ACLTest");
map.put("testCaseName","DCLAddTest");
System.out.println(map);
Output :
{testCaseName=DCLAddTest}
So you have to fix that too.
Look at the output of the call
String arr[] = str[i].split(":");
arr[1] does not exists for the first element in your CSV file which happens to be 1, 2... You can start the loop with int i=0 to fix this issue.
String.split is rubbish for parsing CSV. Either use the Guava Splitter or a proper CSV parser. You can parse CSV into beans using the Jackson CSV mapper like this:
public class CSVPerson{
public String firstname;
public String lastname;
//etc
}
CsvMapper mapper = new CsvMapper();
CsvSchema schema = CsvSchema.emptySchema().withHeader().withColumnSeparator(delimiter);
MappingIterator<CSVPerson> it = = mapper.reader(CSVPerson).with(schema).readValues(input);
while (it.hasNext()){
CSVPerson row = it.next();
}
more info at http://demeranville.com/how-not-to-parse-csv-using-java/
Beside the problem you have with the first number which its not a pair and its causing the Exception, you will not want to use Hashmap, since hashmap use a unique key, so line 2 will replace values from line 1.
You should use a MultiMap, or a List of pairs in this case.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
public class Example {
public static void main(String[] args) {
String csvFile = "test.csv";
String line = "";
String cvsSplitBy = ",";
HashMap<String, String> list = new HashMap<>();
try (BufferedReader br = new BufferedReader(new FileReader(csvFile))) {
while ((line = br.readLine()) != null) {
// use comma as separator
String[] country = line.split(cvsSplitBy);
//System.out.println(country[0] +" " + country[1]);
list.put(country[0], country[1]);
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(list);
}
// enter code here
}
using openCSV would be one way to do it
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import au.com.bytecode.opencsv.CSVReader;
public class CsvFileReader {
public static void main(String[] args) {
try {
System.out.println("\n**** readLineByLineExample ****");
String csvFilename = "C:/Users/hussain.a/Desktop/sample.csv";
CSVReader csvReader = new CSVReader(new FileReader(csvFilename));
String[] col = null;
while ((col = csvReader.readNext()) != null)
{
System.out.println(col[0] );
//System.out.println(col[0]);
}
csvReader.close();
}
catch(ArrayIndexOutOfBoundsException ae)
{
System.out.println(ae+" : error here");
}catch (FileNotFoundException e)
{
System.out.println("asd");
e.printStackTrace();
} catch (IOException e) {
System.out.println("");
e.printStackTrace();
}
}
}
the jar is available here

Read file and get key=value without using java.util.Properties

I'm building a RMI game and the client would load a file that has some keys and values which are going to be used on several different objects. It is a save game file but I can't use java.util.Properties for this (it is under the specification). I have to read the entire file and ignore commented lines and the keys that are not relevant in some classes. These properties are unique but they may be sorted in any order. My file current file looks like this:
# Bio
playerOrigin=Newlands
playerClass=Warlock
# Armor
playerHelmet=empty
playerUpperArmor=armor900
playerBottomArmor=armor457
playerBoots=boot109
etc
These properties are going to be written and placed according to the player's progress and the filereader would have to reach the end of file and get only the matched keys. I've tried different approaches but so far nothing came close to the results that I would had using java.util.Properties. Any idea?
This will read your "properties" file line by line and parse each input line and place the values in a key/value map. Each key in the map is unique (duplicate keys are not allowed).
package samples;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.TreeMap;
public class ReadProperties {
public static void main(String[] args) {
try {
TreeMap<String, String> map = getProperties("./sample.properties");
System.out.println(map);
}
catch (IOException e) {
// error using the file
}
}
public static TreeMap<String, String> getProperties(String infile) throws IOException {
final int lhs = 0;
final int rhs = 1;
TreeMap<String, String> map = new TreeMap<String, String>();
BufferedReader bfr = new BufferedReader(new FileReader(new File(infile)));
String line;
while ((line = bfr.readLine()) != null) {
if (!line.startsWith("#") && !line.isEmpty()) {
String[] pair = line.trim().split("=");
map.put(pair[lhs].trim(), pair[rhs].trim());
}
}
bfr.close();
return(map);
}
}
The output looks like:
{playerBoots=boot109, playerBottomArmor=armor457, playerClass=Warlock, playerHelmet=empty, playerOrigin=Newlands, playerUpperArmor=armor900}
You access each element of the map with map.get("key string");.
EDIT: this code doesn't check for a malformed or missing "=" string. You could add that yourself on the return from split by checking the size of the pair array.
I 'm currently unable to come up with a framework that would just provide that (I'm sure there are plenty though), however, you should be able to do that yourself.
Basically you just read the file line by line and check whether the first non whitespace character is a hash (#) or whether the line is whitespace only. You'd ignore those lines and try to split the others on =. If for such a split you don't get an array of 2 strings you have a malformed entry and handle that accordingly. Otherwise the first array element is your key and the second is your value.
Alternately, you could use a regular expression to get the key/value pairs.
(?m)^[^#]([\w]+)=([\w]+)$
will return capture groups for each key and its value, and will ignore comment lines.
EDIT:
This can be made a bit simpler:
[^#]([\w]+)=([\w]+)
After some study i came up with this solution:
public static String[] getUserIdentification(File file) throws IOException {
String key[] = new String[3];
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
String lines;
try {
while ((lines = br.readLine()) != null) {
String[] value = lines.split("=");
if (lines.startsWith("domain=") && key[0] == null) {
if (value.length <= 1) {
throw new IOException(
"Missing domain information");
} else {
key[0] = value[1];
}
}
if (lines.startsWith("user=") && key[1] == null) {
if (value.length <= 1) {
throw new IOException("Missing user information");
} else {
key[1] = value[1];
}
}
if (lines.startsWith("password=") && key[2] == null) {
if (value.length <= 1) {
throw new IOException("Missing password information");
} else {
key[2] = value[1];
}
} else
continue;
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
return key;
}
I'm using this piece of code to check the properties. Of course it would be wiser to use Properties library but unfortunately I can't.
The shorter way how to do that:
Properties properties = new Properties();
String confPath = "src/main/resources/.env";
try {
properties.load(new FileInputStream(confPath));
} catch (IOException e) {
e.printStackTrace();
}
String specificValueByKey = properties.getProperty("KEY");
Set<Object> allKeys = properties.keySet();
Collection<Object> values = properties.values();

Categories