Java ArrayList split each object - java

I'm trying to split each object in the ArrayList because a lot of lines contains comma(","). Each object contains a item and value(but not all objects contains value):
Access control enable ,disabled
Access policy prototyping ,enabled
Access user group
Implicit roles access policy
World access policy ,disabled
This is my piece of code:
List<String> CEP = new ArrayList<String>();
List<String> CEV = new ArrayList<String>();
for (String str : CE) {
for (String s : str.split(",")) {
CEP.add(s.trim());
}
}
"CE" is the main ArrayList.
"CEP" is the ArrayList that should contain only the "items"(what before comma).
"CEV" is the ArrayList that should contain all "values"
My piece of code only split it by comma to the same ArrayList and another problem is how to see an object doesn't have "value" and add blank to the values ArrayList.
Thanks guys.

Maybe using a CSV parser like super-csv is a good option. It will really pay off when your comma separated list starts to become more diverse.
Univocity provides a benchmark of CSV parsers. It says that univocity-parsers
is fast, which is no surprise. You could give it a try.

Using an array and checking its length allows you to handle the missing values:
for (String str : CE) {
String[] a = str.split(",");
CEP.add(a[0].trim());
if(a.length > 1) {
CEV.add(a[1].trim());
} else {
CEV.add(null); //just check that this is OK
}
}
Just make sure that the value being added to CEV for missing values (null in the above code) is as required.

You could split and check the length of the array afterwards:
public static void main(String[] args) {
List<String> ce = new ArrayList<String>();
ce.add("Access control enable ,disabled");
ce.add("Access policy prototyping ,enabled");
ce.add("Access user group ");
ce.add("Implicit roles access policy ");
ce.add("World access policy ,disabled");
Map<String, String> cepCev = new HashMap<String, String>();
ce.forEach((String line) -> {
String[] splitLine = line.split(",");
if (splitLine.length > 1) {
cepCev.put(splitLine[0].trim(), splitLine[1].trim());
} else {
cepCev.put(splitLine[0].trim(), "not set");
}
});
cepCev.forEach((String key, String value) -> {
System.out.println(key + ": " + value);
});
}

You can do it using java 8 and steam in simple way,
List<String> CEP = new ArrayList<String>();
CE.stream().forEach(ce->CEP.addAll(Arrays.asList(ce.split(","))));
List<String> CEV= CEP.stream().map(String::trim).filter(s -> s.length()>0).collect(Collectors.toList());
System.out.println(CEP);
System.out.println(CEV);

Related

Deal with large amount of strings to validation with two for-loop iteration

I'm facing this problem and kinda dont know how to deal with it. I need to process a csv file that can contain 100 or 100 thousand lines.
I need to do some validations before to proceed the processing, one of them is to check if each document has same typeOfDoc. Let me explain:
Content of file:
document;typeOfDoc
25693872076;2
25693872076;2
...
25693872076;1
This validations consists in check if to document has different type of typeOfDoc along the file, and if it is, show that's invalid.
Initially I thinked in two for-loop to iterate over first occurrence of document (which I assume that's correct, because I don't know what I'm going to receive), and for that correct document I iterate over the rest of file to verify if has another occurence of it, and if have same document but if typeOfDoc is different of first occurence, I store this validation on a object to show that this file has one document with two different types. But.... you'll imagine where it is going. This can't happen with 100k lines, even with 100.
Which is the better way to do that?
Something that can help.
This is how I open and process the file (try-catch, close(), and properly names were omitted):
List<String> lines = new BufferedReader(new FileReader(path)).lines().skip(1).collect(Collectors.toList());
for (String line : lines) {
String[] arr = line.split(";");
String document = arr[0];
String typeOfDoc = arr[1];
for (String line2 : lines) {
String[] arr2 = line2.split(";");
String document2 = arr2[0];
String typeOfDoc2 = arr2[1];
if (document.equals(document2) && !typeOfDoc.equals(typeOfDoc2)) {
...create object to show that error on grid...
}
}
}
You can try to look for duplicate keys and values in a Hashmap, which makes it easier.
public class App {
public static void main(String[] args) throws IOException {
String delimiter = ";";
Map<String, String> map = new HashMap<>();
Stream<String> lines = Files.lines(Paths.get("somefile.txt"));
lines.forEach(line -> checkAndPutInMap(line,map,delimiter));
lines.close();
}
private static void checkAndPutInMap(String line, Map<String,String> map, String delimiter) {
String document = line.split(delimiter)[0];
String typeOfDoc = line.split(delimiter)[1];
if (map.containsKey(document) && !map.get(document).equals(typeOfDoc)) {
...create object to show that error on grid...
}
else
map.put(document, typeOfDoc));
}
}

manipulating strings withinside an arraylist

I have built an ArrayList of strings from two sources:
Path p1 = Paths.get("C:/Users/Green/documents/dictionary.txt");
Scanner sc = new Scanner(p1.toFile()).useDelimiter("\\s*-\\s*");
ArrayList al = new ArrayList();
while (sc.hasNext()) {
String word = (sc.next());
al.add(word);
al.add(Translate(word));
}
The array is made up of a word from a text file dictionary read one line at a time. The second is a translation of the word. The translation Translate is a Java method that now returns a string. so I am adding two strings to the array list for as many lines that there are in the dictionary.
I can print the dictionary out and the translations....but the printout is unhelpful as it prints all the words and then all the translations....not much use to quickly look up.
for(int i=0;i<al.size();i++){
al.forEach(word ->{ System.out.println(word); });
}
Is there a way that I can either manipulate the way I add the strings to the ArrayList or how I manipulate after so that I can retrieve one word and its translation at a time.
Ideally I want to be able to sort the dictionary as the file I receive is not in alphabetic order.
I am not sure why you have to use ArrayList data structure as it is required or not.
I would suggest you use the Map for this kind of dictionary data. Map data structure will manage your data as a key which is your original word and a value which is a translated word.
Here is a simple example:
Path p1 = Paths.get("C:/Users/Green/documents/dictionary.txt");
Scanner sc = new Scanner(p1.toFile()).useDelimiter("\\s*-\\s*");
Map<String, String> dic = new HashMap<String, String>();
while (sc.hasNext()) {
String word = (sc.next());
dic.put(word, Translate(word));
}
//print out from dictionary data
for(Map.Entry<String, String> entry: dic.entrySet()){
System.out.println(dic.getKey() + " - " + dic.getValue());
}
You can use object like this
class Word {
String original;
String translation;
public Word(String original, String translation) {
this.original = original;
this.translation = translation;
}
}
Put words to list:
while (sc.hasNext()) {
String word = (sc.next());
al.add(new Word(word, Translate(word)));
}
And then:
for (Word word : al) {
}

How to add strings into an arraylist between two strings

I am trying to figure out how to add a string, into a string ArrayList, between two strings that are already in. So if I have this
ArrayList<String> List = new ArrayList<String>();
List.add("Yes");
List.add("No");
List.add("Maybe");
How would I go along putting the word "Or" between them and make the ArrayList contain
"Yes" "Or" "No" "Or" "Maybe"?
I have three advices.
First, to name the variables, start with lower-case.
Second, use List as type of variable, instead of ArrayList, you will thank me later, trust me.
Third, to do what you ask for, there is overloaded method add for choosing position :
List<String> list = new ArrayList<String>();
list.add("Yes");
list.add("No");
list.add(1,"Maybe"); //insert into position 1 and shift everything to the right.
For this example, if you use System.out.println(list);, you will get this output :
[Yes, Maybe, No]
For adding Or instruction, it would be like this :
List<String> list = new ArrayList<String>();
list.add("Yes");
list.add("No");
list.add("Maybe");
list.add(1, "Or");
list.add(3, "Or");
System.out.println(list);
Output :
[Yes, Or, No, Or, Maybe]
Also, if you want to make your program more re-usable, you can write a method, that will do this for you for any case of list :
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("Yes");
list.add("No");
list.add("Maybe");
list.add("Probably");
list.add("Never");
List<String> orList = addOr(list);
System.out.println(orList);
}
public static List<String> addOr(List<String> list){
List<String> newList = new ArrayList<>();
int count = 0;
for(String text : list){
count++;
newList.add(text);
if (count != list.size()){
newList.add("Or");
}
}
return newList;
}
Having this output :
[Yes, Or, No, Or, Maybe, Or, Probably, Or, Never]
However, if you want to use that list for outputing some message for user, it is not good idea to add "Or", because it is really not part of information. Rather it is good, to create method, which will create output String you desire.
This code
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("Yes");
list.add("No");
list.add("Maybe");
list.add("Probably");
list.add("Never");
String niceOutput = addOr(list);
System.out.println("Choose from following options: " + niceOutput);
}
public static String addOr(List<String> list){
String orText = "";
int count = 0;
for(String text : list){
count++;
orText += '\'' + text + '\'';
if (count != list.size()){
orText += " or ";
}
}
return orText;
}
Having this output :
Choose from following options: 'Yes' or 'No' or 'Maybe' or 'Probably' or 'Never'
According to Add object to ArrayList at specified index
List.add(1, "or")
List.add(3, "or")
This should solve your problem.

Best way to create categories with words

I am currently working on a little "Hangman" project. I want to make it possible for the user to choose from different categories, such as "Countries" or "Food" and this got me thinking about what would be the best way to handle and sort those categories.
I saved the words to a little text file, which looks something like this:
Countries: Hungary Austria Argentina Canada;
Food: Donut Bread Hamburger;
For now, I created a multidimensional ArrayList that stores all the words, each category in an individual ArrayList in that ArrayList.
ArrayList< ArrayList<String> > words = new ArrayList< ArrayList<String> >();
// ... read words from .txt file and store it in the words-ArrayList ...
I know, that in each category the first word is the title of a category, so if I wanted to get all the titles of the categories, it would look something like this:
for( ArrayList list : words ) {
System.out.println( list.get(0) );
}
Now this method I'm using works perfectally fine, it just seems a bit too complex to me and I was wondering, if there are simpler methods to do that. I want to thank in advance for any suggestions you can give me.
Better to use Map<String, List<String>> for my money. The Map can be a HashMap, and the word category would be the key while the List (an ArrayList in the concrete form) would be the related value.
Then to extract the categories, all you'd need to do would be to extract the key set and iterate through it. e.g.,
Map<String, List<String>> mapList = new HashMap<String, List<String>>();
// fill map here...
for (String key : mapList.keySet()) {
List<String> list = mapList.get(key);
System.out.printf("%s: %s%n", key, list);
}
If you want the keys to be in a certain order, then you'd need to use one of the other concrete implementations of Map such as a TreeMap.
For a simple example:
import java.io.InputStream;
import java.util.*;
public class MapList {
public static void main(String[] args) {
Map<String, List<String>> mapList = new HashMap<String, List<String>>();
String sourcePath = "MapListData.txt";
InputStream source = MapList.class.getResourceAsStream(sourcePath);
if (source == null) {
return;
}
Scanner scan = new Scanner(source);
while (scan.hasNextLine()) {
String line = scan.nextLine().trim();
if (!line.isEmpty()) {
line = line.replace(";", "");
String[] mainTokens = line.split("\\s*:\\s*");
if (mainTokens.length == 2) {
String key = mainTokens[0];
List<String> list = new ArrayList<String>();
String[] subTokens = mainTokens[1].split("\\s+");
for (String subToken : subTokens) {
list.add(subToken);
}
mapList.put(key, list);
}
}
}
if (scan != null) {
scan.close();
}
for (String key : mapList.keySet()) {
List<String> list = mapList.get(key);
System.out.printf("%s: %s%n", key, list);
}
}
}
For me returns:
Beer: [Pilsner, Weiss, Brown_Ale, IPA]
Countries: [Hungary, Austria, Argentina, Canada]
Food: [Donut, Bread, Hamburger]

Extracting token from a string

I've a some strings like that "paddington road" and I need to extract the word "road" from this string. How can I do that?
The problem is that I need to process a list of streets and extract some words like "road" "park" "street" "boulevard" and many others.
What could be the best way to do that? The complexity is O(n*m) and if you consider that I process more than 5000 streets, the performance should be very important.
I'm extracting the values from a Postgres db and putting into a List but I'm not sure it's the best way, may be a hash table is faster to query?
I tried something like this:
// Parse selectedList
Iterator<String> it = streets.iterator();
Iterator<String> it_exception = exception.iterator();
int counter = streets.size();
while(it.hasNext()) {
while ( it_exception.hasNext() ) {
// remove substring it_exception.next() from it.next()
}
}
What do you think?
You can try Set:
Set<String> exceptions = new HashSet<String>(...);
for (String street : streets) {
String[] words = street.split(" ");
StringBuilder res = new StringBuilder();
for (String word : words) {
if (!exceptions.contains(word)) {
res.append(word).append(" ");
}
}
System.out.println(res);
}
I think complexity will be O(n), where n is a number of all words in streets.
You need to get a new iterator for your list of keywords at each iteration of the outer loop. The easiest way is to use the foreach syntax:
for (String streetName : streets) {
for (String keyword : keywords) {
// find if the string contains the keyword, and perhaps break if found to avoid searching for the other keywords
}
}
Don't preoptimize. 5000 is nothing for a computer, and street names are short strings. And if you place the most frequent keywords (street, rather than boulevard) at the beginning of the keyword list, you'll have less iterations.
List streets = new ArrayList<String>();
streets.add("paddington road");
streets.add("paddington park");
for (Object object : streets) {
String cmpstring = object.toString();
String[] abc = cmpstring.split(" ");
String secondwrd = abc[1];
System.out.println("secondwrd"+secondwrd);
}
you can keep secondwrd in a list or string buffer etc....

Categories