I have written the constructor below that takes a word from a file, passes it to an external method 'Translate' that returns a translation of the word.
In parallel (and for code that I have not jet fully written) the constructor takes a string word as an that it will (once the code is written) find the word in the dictionary.
But before I do that I need to put both the word and the translation in an ArrayList. I know that a Map would be better but I need to use an ArrayList.
My code does this but there is something that I do not understand.
I write the word to the array list and then the translation....so I would expect the ArrayList to be Word1,Translation1,Word2,Translation2,
But when I run my print command it prints all the words and then all the translations...
The reason that I am trying to fathom this out is that I want to be able to sort the array list on word (the dictionary is unsorted) and then look up an individual word....and quickly pick up its translation
So my question is - am I using the ArrayList correctly (accepting the limitations of the ArrayList for this exercise and how can I sort using word as the key?
import java.io.FileNotFoundException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Scanner;
class Translate {
String original;
String translation;
public Translate(String original) throws FileNotFoundException {
this.original = original;
this.translation = translation;
ArrayList al = new ArrayList();
Path p1 = Paths.get("C:/Users/Green/documents/dictionary.txt");
Scanner sc = new Scanner(p1.toFile()).useDelimiter("\\s*-\\s*");
while (sc.hasNext()) {
String word = (sc.next());
String translation = (Translate(word));
al.add(word);
al.add(translation);
System.out.println("Print Arraylist using for loop");
for(int i=0; i < al.size(); i++) {
System.out.println( al.get(i));
}
}
}
public static void main(String args[]) throws FileNotFoundException {
Translate gcd = new Translate("envolope");
}
}
Arranging Strings in an Alphabetical Order with Java 7 (Classic way):
for (int i = 0; i < count; i++) {
for (int j = i + 1; j < count; j++) {
if (str[i].compareTo(str[j])>0) {
temp = str[i];
str[i] = str[j];
str[j] = temp;
}
}
}
Sorting the strings Java 8:
arrayList.sort((p1, p2) -> p1.compareTo(p2));
Using Comparator Java 8:
arrayList.sort(Comparator.comparing(MyObject::getA));
Find word Java 7:
List <String> listClone = new ArrayList<String>();
for (String string : list) {
if(string.matches("(?i)(text).*")) {
listClone.add(string);
}
}
Using a java.util.HashSet:
Set<String> set = new HashSet<String>(list);
if (set.contains("text")) {
System.out.println("String found!");
}
Using contains:
for (String s : list) {
if (s.contains("text")) {
System.out.println(s);
}
}
Find word Java 8:
List<String> matches = list.stream()
.filter(it -> it.contains("txt"))
.collect(Collectors.toList());
Performance of contains() in a HashSet vs ArrayList:
The contains() method works faster in HashSet compared to an ArrayList
Reference:
How to search for a string in an arraylist
Sorting ArrayList with Lambda in Java 8
HashSet vs ArrayList contains performance
https://www.baeldung.com/java-hashset-arraylist-contains-performance
https://beginnersbook.com/2018/10/java-program-to-sort-strings-in-an-alphabetical-order/
Related
I have the following code:
package sportsCardsTracker;
import java.io.*;
import java.text.*;
import java.util.*;
import java.util.stream.Collectors;
public class Test_Mark6 {
public static ArrayList<String> listingNameList;
public static ArrayList<String> finalNamesList;
public static void main(String[] args) throws IOException, ParseException {
listingNameList = new ArrayList();
listingNameList.add("LeBron James 2017-18 Hoops Card");
listingNameList.add("Stephen Curry Auto Patch, HOT INVESTMENTS!");
listingNameList.add("Michael Jordan 1998 Jersey Worn Card");
ArrayList<String> playersNamesList = new ArrayList();
playersNamesList.add("LeBron James");
playersNamesList.add("Stephen Curry");
playersNamesList.add("Michael Jordan");
finalNamesList = new ArrayList();
String directory = System.getProperty("user.dir");
File file = new File(directory + "/src/sportsCardsTracker/CardPrices.csv");
FileWriter fw = new FileWriter(file, false); //true to not over ride
for (int i = 0; i < listingNameList.size(); i++) {
for (String listingNames : listingNameList) {
List<String> result = NBARostersScraper_Mark3.getNBARoster().stream().map(String::toLowerCase).collect(Collectors.toList());
boolean valueContained = result.stream().anyMatch(s -> listingNames.toLowerCase().matches(".*" + s + ".*"));
if(valueContained == true) {
finalNamesList.add(//The players' name);
}
}
fw.write(String.format("%s, %s\n", finalNamesList.get(i)));
}
}
}
Basically, in the listingsNameList, I have the listing's names and in the playersNamesList, I have all the players' names. What I would like is that, if the code matches the names between the two arrayList and find a player's name, it should returns the players' only.
For example, instead of "LeBron James 2017-18 Hoops Card" it should return "Lebron James" only. If it does not find anything, then just return the listing's name. So far, I have created a new ArrayList namely finalNamesList, my idea would be using an if statement (if match found then add players' name to finalNamesList, if not add the listing' name to finalNamesList). However the code above is not working and it is just adding all of the names in the listingNameList to the finalNamesList. I suspect that the way I grab the index is wrong - but I don't know how to fix it.
The method you are using to match a pattern that seems wrong. Instead of "match()" you can use string contains method as below.
List<String> temp = new ArrayList<>();
for (String listingNames : listingNameList) {
temp = playersNamesList.parallelStream().filter(s -> listingNames.toLowerCase().contains(s.toLowerCase())).map(s -> s).collect(Collectors.toList());
if(temp.size() > 0){
System.out.println(temp.get(0));
//fw.write(String.format("%s, %s\n", temp.get(0));
}
}
One more thing, You don't need to use 2 for loop here, with one loop you can achieve your output.
Though You can still optimize this code, I have taken the temp list above that you can avoid.
This question already has answers here:
How to change value of ArrayList element in java
(7 answers)
Closed 6 years ago.
Assume I have an ArrayList of Strings that holds the words, "hello" and "world". I want to add the word "java" to the end of each.
I have tried to do it while looping, but did not succeed. Please suggest me a method for the same.
The other way, I found was to create a different ArrayList and copy contents, however I don't think is efficient in terms of space.
import java.util.ArrayList;
public class EditArrayListInLoop {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add("hello");
arrayList.add("world");
/* This does not work */
/*for(int i = 0;i<arrayList.size();i++)
{
arrayList.get(i) += "java";
}*/
ArrayList<String> arrayList2 = new ArrayList<String>();
for(int i = 0;i<arrayList.size();i++)
{
String test = arrayList.get(i);
test += "java";
arrayList2.add(test);
}
System.out.println(arrayList2);
}
}
test += "java"; doesn't change the content of the String returned by arrayList.get(i). It creates a new String. Strings are immutable, so there isn't any way to change the String objects within the List. You can only replace them by new String objects.
Use arrayList.set(index,newValue) to replace the i'th element of the List:
for(int i = 0;i<arrayList.size();i++)
{
arrayList.set(i,arrayList.get(i)+"java");
}
I think you should manipulate the first list only. Using an another list is not an optimal solution.
Here's the code.
Output
[hellojava, worldjava]
Code
import java.util.ArrayList;
public class EditArrayListInLoop {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add("hello");
arrayList.add("world");
for(int i = 0;i<arrayList.size();i++)
arrayList.set(i, arrayList.get(i).concat("java"));
System.out.println(arrayList);
}
}
Please note that Strings are immutable. Whenever you change the content of String, you're not actually appending anything behind the scenes. You are creating a completely new String.
If the contents of your Strings are expected to change, then the advisable way is to use the StringBuilder class instead:
Documentation
The principal operations on a StringBuilder are the append and insert
methods, which are overloaded so as to accept data of any type. Each
effectively converts a given datum to a string and then appends or
inserts the characters of that string to the string builder. The
append method always adds these characters at the end of the builder;
the insert method adds the characters at a specified point.
Here's the code:
import java.util.ArrayList;
public class EditArrayListInLoop {
public static void main(String[] args) {
ArrayList<StringBuilder> arrayList = new ArrayList<StringBuilder>();
arrayList.add(new StringBuilder("hello"));
arrayList.add(new StringBuilder("world"));
for(int i = 0;i<arrayList.size();i++)
arrayList.set(i, arrayList.get(i).append("java"));
System.out.println(arrayList);
}
}
P.S.: If such synchronization is required then it is recommended that StringBuffer be used.
try using the set method.
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add("hello");
arrayList.add("world");
for(int i = 0;i<arrayList.size();i++)
{
String str = arrayList.get(i);
arrayList.set(i, str + " java");
}
for(int i = 0;i<arrayList.size();i++)
{
String str = arrayList.get(i);
System.out.println(str);
}
You are looking for:
arrayList.set(i, arrayList.get(i) + "java");
More info on ArrayList: https://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html
I am a beginner in Java. Basically, I have loaded each text document and stored each individual words in the text document in the hasmap. Afterwhich, I tried storing all the hashmaps in an ArrayList. Now I am stuck with how to retrieve all the words in my hashmaps that is in the arraylist!
private static long numOfWords = 0;
private String userInputString;
private static long wordCount(String data) {
long words = 0;
int index = 0;
boolean prevWhiteSpace = true;
while (index < data.length()) {
//Intialise character variable that will be checked.
char c = data.charAt(index++);
//Determine whether it is a space.
boolean currWhiteSpace = Character.isWhitespace(c);
//If previous is a space and character checked is not a space,
if (prevWhiteSpace && !currWhiteSpace) {
words++;
}
//Assign current character's determination of whether it is a spacing as previous.
prevWhiteSpace = currWhiteSpace;
}
return words;
} //
public static ArrayList StoreLoadedFiles()throws Exception{
final File f1 = new File ("C:/Users/Admin/Desktop/dataFiles/"); //specify the directory to load files
String data=""; //reset the words stored
ArrayList<HashMap> hmArr = new ArrayList<HashMap>(); //array of hashmap
for (final File fileEntry : f1.listFiles()) {
Scanner input = new Scanner(fileEntry); //load files
while (input.hasNext()) { //while there are still words in the document, continue to load all the words in a file
data += input.next();
input.useDelimiter("\t"); //similar to split function
} //while loop
String textWords = data.replaceAll("\\s+", " "); //remove all found whitespaces
HashMap<String, Integer> hm = new HashMap<String, Integer>(); //Creates a Hashmap that would be renewed when next document is loaded.
String[] words = textWords.split(" "); //store individual words into a String array
for (int j = 0; j < numOfWords; j++) {
int wordAppearCount = 0;
if (hm.containsKey(words[j].toLowerCase().replaceAll("\\W", ""))) { //replace non-word characters
wordAppearCount = hm.get(words[j].toLowerCase().replaceAll("\\W", "")); //remove non-word character and retrieve the index of the word
}
if (!words[j].toLowerCase().replaceAll("\\W", "").equals("")) {
//Words stored in hashmap are in lower case and have special characters removed.
hm.put(words[j].toLowerCase().replaceAll("\\W", ""), ++wordAppearCount);//index of word and string word stored in hashmap
}
}
hmArr.add(hm);//stores every single hashmap inside an ArrayList of hashmap
} //end of for loop
return hmArr; //return hashmap ArrayList
}
public static void LoadAllHashmapWords(ArrayList m){
for(int i=0;i<m.size();i++){
m.get(i); //stuck here!
}
Firstly your login wont work correctly. In the StoreLoadedFiles() method you iterate through the words like for (int j = 0; j < numOfWords; j++) { . The numOfWords field is initialized to zero and hence this loop wont execute at all. You should initialize that with length of words array.
Having said that to retrieve the value from hashmap from a list of hashmap, you should first iterate through the list and with each hashmap you could take the entry set. Map.Entry is basically the pair that you store in the hashmap. So when you invoke map.entrySet() method it returns a java.util.Set<Map.Entry<Key, Value>>. A set is returned because the key will be unique.
So a complete program will look like.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
import java.util.Scanner;
public class FileWordCounter {
public static List<HashMap<String, Integer>> storeLoadedFiles() {
final File directory = new File("C:/Users/Admin/Desktop/dataFiles/");
List<HashMap<String, Integer>> listOfWordCountMap = new ArrayList<HashMap<String, Integer>>();
Scanner input = null;
StringBuilder data;
try {
for (final File fileEntry : directory.listFiles()) {
input = new Scanner(fileEntry);
input.useDelimiter("\t");
data = new StringBuilder();
while (input.hasNext()) {
data.append(input.next());
}
input.close();
String wordsInFile = data.toString().replaceAll("\\s+", " ");
HashMap<String, Integer> wordCountMap = new HashMap<String, Integer>();
for(String word : wordsInFile.split(" ")){
String strippedWord = word.toLowerCase().replaceAll("\\W", "");
int wordAppearCount = 0;
if(strippedWord.length() > 0){
if(wordCountMap.containsKey(strippedWord)){
wordAppearCount = wordCountMap.get(strippedWord);
}
wordCountMap.put(strippedWord, ++wordAppearCount);
}
}
listOfWordCountMap.add(wordCountMap);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if(input != null) {
input.close();
}
}
return listOfWordCountMap;
}
public static void loadAllHashmapWords(List<HashMap<String, Integer>> listOfWordCountMap) {
for(HashMap<String, Integer> wordCountMap : listOfWordCountMap){
for(Entry<String, Integer> wordCountEntry : wordCountMap.entrySet()){
System.out.println(wordCountEntry.getKey() + " - " + wordCountEntry.getValue());
}
}
}
public static void main(String[] args) {
List<HashMap<String, Integer>> listOfWordCountMap = storeLoadedFiles();
loadAllHashmapWords(listOfWordCountMap);
}
}
Since you are beginner in Java programming I would like to point out a few best practices that you could start using from the beginning.
Closing resources : In your while loop to read from files you are opening a Scanner like Scanner input = new Scanner(fileEntry);, But you never closes it. This causes memory leaks. You should always use a try-catch-finally block and close resources in finally block.
Avoid unnecessary redundant calls : If an operation is the same while executing inside a loop try moving it outside the loop to avoid redundant calls. In your case for example the scanner delimiter setting as input.useDelimiter("\t"); is essentially a one time operation after a scanner is initialized. So you could move that outside the while loop.
Use StringBuilder instead of String : For repeated string manipulations such as concatenation should be done using a StringBuilder (or StringBuffer when you need synchronization) instead of using += or +. This is because String is an immutable object, meaning its value cannot be changed. So each time when you do a concatenation a new String object is created. This results in a lot of unused instances in memory. Where as StringBuilder is mutable and values could be changed.
Naming convention : The usual naming convention in Java is starting with lower-case letter and first letter upper-case for each word. So its a standard practice to name a method as storeLoadedFiles as opposed to StoreLoadedFiles. (This could be opinion based ;))
Give descriptive names : Its a good practice to give descriptive names. It helps in later code maintenance. Say its better to give a name as wordCountMap as opposed to hm. So in future if someone tries to go through your code they'll get a better and faster understanding about your code with descriptive names. Again opinion based.
Use generics as much as possible : This avoid additional casting overhead.
Avoid repetition : Similar to point 2 if you have an operation that result in the same output and need to be used multiple times try moving it to a variable and use the variable. In your case you were using words[j].toLowerCase().replaceAll("\\W", "") multiple times. All the time the result is the same but it creates unnecessary instances and repetitions. So you could move that to a String and use that String elsewhere.
Try using for-each loop where ever possible : This relieves us from taking care of indexing.
These are just suggestions. I tried to include most of it in my code but I wont say its the perfect one. Since you are a beginner if you tried to include these best practices now itself it'll get ingrained in you. Happy coding.. :)
for (HashMap<String, Integer> map : m) {
for(Entry<String,Integer> e:map.entrySet()){
//your code here
}
}
or, if using java 8 you can play with lambda
m.stream().forEach((map) -> {
map.entrySet().stream().forEach((e) -> {
//your code here
});
});
But before all you have to change method signature to public static void LoadAllHashmapWords(List<HashMap<String,Integer>> m) otherwise you would have to use a cast.
P.S. are you sure your extracting method works? I've tested it a bit and had list of empty hashmaps all the time.
I am trying to work out the solution to the above problem and I came up with this
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
public class Subset_K {
public static void main(String[]args)
{
Set<String> x;
int n=4;
int k=2;
int arr[]={1,2,3,4};
StringBuilder sb=new StringBuilder();
for(int i=1;i<=(n-k);i++)
sb.append("0");
for(int i=1;i<=k;i++)
sb.append("1");
String bin=sb.toString();
x=generatePerm(bin);
Set<ArrayList <Integer>> outer=new HashSet<ArrayList <Integer>>();
for(String s:x){
int dec=Integer.parseInt(s,2);
ArrayList<Integer> inner=new ArrayList<Integer>();
for(int j=0;j<n;j++){
if((dec&(1<<j))>0)
inner.add(arr[j]);
}
outer.add(inner);
}
for(ArrayList<Integer> z:outer){
System.out.println(z);
}
}
public static Set<String> generatePerm(String input)
{
Set<String> set = new HashSet<String>();
if (input == "")
return set;
Character a = input.charAt(0);
if (input.length() > 1)
{
input = input.substring(1);
Set<String> permSet = generatePerm(input);
for (String x : permSet)
{
for (int i = 0; i <= x.length(); i++)
{
set.add(x.substring(0, i) + a + x.substring(i));
}
}
}
else
{
set.add(a + "");
}
return set;
}
}
I am working on a 4 element set for test purpose and using k=2. What I try to do is initially generate a binary string where k bits are set and n-k bits are not set. Now using this string I find all the possible permutations of this string. And then using these permutations I output the respective element in the set. Now i cant figure out the complexity of this code because I used the generatePerm method from someone else. Can someone help me with the time complexity of the generatePerm method and also the overall time complexity of my solution. I found other recursive implementation of this problem in here Find all subsets of length k in an array However I cant figure out the complexity of it either. So need some help there.
Also I was trying to re-factor my code so that its not just for integers but for all types of data. I dont have much experience with generics. so when I try to modify ArrayList< Integer> to ArrayList< ?> in line 21 eclipse says
Cannot instantiate the type ArrayList< ?>
How do I correct that?
You can use ArrayList<Object> throughout. That will accept any kind of object. If you want a specific type that is determined by the calling code, you will need to introduce a generic type parameter.
Note that in your generatePerm method, you should not use the test
if (input == "")
Instead, you should use:
if ("".equals(input))
Your current code will only succeed if input is the interned string "". It will not work, for instance, if input is computed as a substring() with zero length. In general you should always compare strings with .equals() rather than with == (except under very specific conditions when you are looking for object identity rather than object equality).
I am piping in a file. I am tracking word pairs from the file. Using a treemap the keys are all sorted. However, when i add words to those keys they are not sorted.
here is the part i need help on in the process function:
private static void process(){
if(!result.containsKey(thisWord)){
result.put(thisWord, new ArrayList<String>());
}
// Add nextWord to the list of adjacent words to thisWord:
result.get(thisWord).add(nextWord); // nextword is not sorted within the key
thisword is sorted
nextWord is not..
Can i use Collections.sort(result); somehow?
im just not sure how i get to the nextWord within the result to do that.
or, is there no way to do it within my situation. I would rather not change things unless you recommend it.
This is the program
import java.util.Map.Entry;
import java.util.TreeSet;
import java.io.*;
import java.util.*;
public class program1 {
private static List<String> inputWords = new ArrayList<String>();
private static Map<String, List<String>> result = new TreeMap<String, List<String>>();
public static void main(String[] args) {
collectInput();
process();
generateOutput();
}
private static void collectInput(){
Scanner sc = new Scanner(System.in);
String word;
while (sc.hasNext()) { // is there another word?
word = sc.next(); // get next word
if (word.equals("---"))
{
break;
}
inputWords.add(word);
}
}
private static void process(){
// Iterate through every word in our input list
for(int i = 0; i < inputWords.size() - 1; i++){
// Create references to this word and next word:
String thisWord = inputWords.get(i);
String nextWord = inputWords.get(i+1);
// If this word is not in the result Map yet,
// then add it and create a new empy list for it.
if(!result.containsKey(thisWord)){
result.put(thisWord, new ArrayList<String>());
}
// Add nextWord to the list of adjacent words to thisWord:
result.get(thisWord).add(nextWord); // need to sort nextword
// Collections.sort(result);
}
}
private static void generateOutput()
{
for(Entry e : result.entrySet()){
System.out.println(e.getKey() + ":");
// Count the number of unique instances in the list:
Map<String, Integer> count = new HashMap<String, Integer>();
List<String> words = (List)e.getValue();
for(String s : words){
if(!count.containsKey(s)){
count.put(s, 1);
}
else{
count.put(s, count.get(s) + 1);
}
}
// Print the occurances of following symbols:
for(Entry f : count.entrySet()){
System.out.println(" " + f.getKey() + ", " + f.getValue() );
}
}
System.out.println();
}
}
If you want the collection of "nextword"s sorted, why not use a TreeSet rather than an ArrayList? The only reason I can see against it is if you might have duplicates. If duplicates are allowed, then yes, use Collections.sort on the ArrayList when you're done adding to them. Or look in the Apache Commons or Google collection classes - I don't know them off the top of my head, but I'm sure there is a sorted List that allows duplicates in one or both of them.
result.get(thisWord).add(nextWord);
Collections.sort(result.get(thisWord));
Y Don't you try some thing like this
Collections.sort(inputWords);