Let say I have an array list with names and the names are stored like this...
John(2),
Bob(anytext),
Rick
I'm trying to iterate over my array list and check for "(" basically and just take the rest of the string behind it and return that as a string, and null if nothing there. I've seen methods to do similar things but I can't seem to find something to just return the rest of the string if it finds the "("
for(int i=0; i<list.size(); i++) {
String s = list.get(i);
int x = s.indexOf('(');
if(x==-1) break;
return s.substring(x+1);
}
Pass the strings you want to check to a method that does something like this:
if(str.contains("(")){
return str.substring(str.indexOf("("));
}else{
return null;
}
Java 8 version
List<String> list = Arrays.asList("John(2)", "Bob(anytext)", "Rick");
String result = list.stream()
.filter(x -> x.contains("("))
.findFirst()
.map(x -> x.substring(x.indexOf("(")))
.orElse(null);
Related
partnersName =["partner1","partner2"];
totalDates = ["2022-05-18","2022-05-19"];
both the lists store string only
here is the following code which gives output that I want
for (int i = 0; i < partnersName.size(); i++) {
if (totalDates.isEmpty()) {
totalDates.add(partnersName.get(i));
} else {
for (int j = 0; j < totalDates.size(); j++) {
totalDates.set(j, partnersName.get(i) +"/" +totalDates.get(j));
}
}
}
output
=["partner1/2022-05-18","partner2/2022-05-18","partner1/2022-05-19","partner2/2022-05-19"];
but I want to reduce the line of code using stream. Anyone could help to get stream API code
Assuming the result [partner1/2022-05-18, partner1/2022-05-19, partner2/2022-05-18, partner2/2022-05-19] is what you want:
List<String> result = partnersName.stream().<String>mapMulti((s, stringConsumer) -> totalDates.forEach(d -> stringConsumer.accept(s + "/" + d))).toList();
Another way can be
List<String> result = partnersName.stream()
.flatMap(x -> totalDates.stream().map(y -> x.concat("/"+y)))
.collect(Collectors.toList());
//output: [partner1/2022-05-18, partner1/2022-05-19, partner2/2022-05-18, partner2/2022-05-19]
Here is one way.
List<String> partnerName = List.of("partner1","partner2");
List<String> totalDates = List.of("2022-05-18","2022-05-19");
List<String> result = partnerName.stream()
.flatMap(name -> totalDates.stream()
.map(date->String.join("/", name, date)))
.toList();
System.out.println(result);
prints
[partner1/2022-05-18, partner1/2022-05-19, partner2/2022-05-18, partner2/2022-05
-19]
The above uses nested streams to process each List.
String.join - takes a delimiter and a variable number of arguments and concatenates them, separated by the delimiter.
flatMap flattens the nested streams into one for conversion to a list.
I extract some Data into a Arraylist. And in every Item there are several line breaks (\n) that I want to get rid of afterwards.
I´ve tried to do this:
public List<String> MemberIDList() {
// Getting the ArrayList
idList = listProjection.getIDListOfMembers();
for (int i = 0; idList.size() > i; i++) {
String item = idList.get(i);
item.replaceAll("\n", "");
}
return idList;
}
If I print that out on the console, it still contains all the line breaks:
The ID ...... (not null)
145
145
Thanks
EDIT: I also want to filter unnecessary whitespace. Is ther a better option than running the answers down below twice. There are spaces --------------------- this huge.
idList.replaceAll(item -> item.replaceAll("\\s{2,}", "").trim());
I got it :D
Change
item.replaceAll("\n", "");
to
idList.set(i,item.replaceAll("\n", ""));
item.replaceAll doesn't modify the state of the String referenced by item (which is impossible, since String is immutable). It returns a new String instead.
You can replace all your method to be like so :
public List<String> memberIDList() {
idList.replaceAll(item -> item.replaceAll("\n", ""));
return idList;
}
You can stream and map them:
idList.stream()
.map(str -> str.replaceAll("\n", ""))
.collect(Collectors.toList());
This will apply function str -> str.replaceAll("\n", "") to every element and collect them back to list. You can use this instead of your MemberIDList method.
P.S.: Method names are starting with lowercase in java.
I'm developing an Android app where I get a List of names (Strings) from a SQLite database. Then, I show them on a List of Cardviews.
I'm also given a substring, so I'd like to check if any of the elements of the original List contains that substring on it.
I'm having problems using LIKE in the SQLite query, so I've just fixed it with a try{ } catch (Exception e) { }, but I don't feel so comfortable with it.
Anyway, since I originally have all of the names stored in the List of Strings, I don't really need to fecth the new ones again from the database, I can just search them on the original List of Strings. But I don't know how.
For example, let's say the List of String has this 5 elements:
Hello
Wall
Helicopter
Chair
Hell
And I'm given the substring Hel. I should get the Hello, Helicopter and Hell strings, since all of them contain the substring Hel.
Any ideas on how to achieve this goal?
It's not that I want to fix it this way. I sincerely would like to know what's the most efficient, if retrieveing the data again from the database, or search it from the List of Strings.
EDIT: I originally said that I was using the CONTAINS query, but I missed the word. I just meant the LIKE query. I'm actually using it, and it works fine but I don't really know what's the most efficient in my case.
Thanks in advance.
Here is my suggestion
public boolean isSubstring(String str, String key) {
if(key.length() > str.length()) return false;
for(int i = 0; i <= str.length() - key.length(); i++) {
if( key.equals(str.substring(i, i + key.length())) ) return true;
}
return false;
}
public List<String> findStings(List<String> list, String key) {
List<String> newList = new ArrayList<>();
for(int i = 0; i < list.size(); i++) {
if(isSubstring(list.get(i), key)) {
newList.add(list.get(i));
}
}
return newList;
}
If you are working with Java 8 you can replace the for-loop of the second method as:
for(String str: list) {
if(isSubstring(str, key)) newList.add(str);
}
or simply as:
list.stream().filter((str) -> (isSubstring(str, key))).forEach((str) -> { newList.add(str); });
If you're using Java 8:
List<String> filteredList = myList.stream().filter(s -> s.contains("Hel")).collect(Collectors.toList());
If you're using anything earlier, use a for each loop:
List<String> filteredList = new ArrayList<String>();
for(String s : myList)
if(s.contains("Hel")
filteredList.add(s);
I try to parse a textfile which has lines which look like the following:
#KEY,_,0,1,2,_,4,5,6, ...
The #KEY is just an identifier in the beginning while the following numbers are my data which I want to store in an ArrayList<Integer>.
I have a metadata class which contains the arraylist in which I want to insert there integers:
class MetaD {
public List<Integer> key1, key2, key3 = new ArrayList<Integer>();
}
I parse the textfile line by line; when the line starts with #KEY, I want to add the elements to the key1 list. If there is an _, it should be replaced with an empty value:
if(line.startsWith("#KEY")){
metaObject.key1 = Arrays.asList(line.replace("#KEY,", "").replace("_", "").trim().split("\\s*,\\s*"));
}
I found out that this does not work with ArrayList<Integer>. key1 has to be of the type ArrayList<String> or ArrayList<Object> to make it work.
Is there a way to convert Integers in the same way?
If not, my idea would be the following:
Convert everything to an ArrayList<String>
Iterate every item of this new ArrayList and convert it with Integer.parseInt() into an Integer.
Adding this new Integer to my ArrayList<Integer>
Would there be a more efficient or better way to archive my needs?
Edit:
Since Tunaki wrote in the comments, that my idea will probably be the only possible way I tried to do the following:
if(line.startsWith("#KEY")){
List<String> channelTemp = Arrays.asList(line.replace("#KEY,", "").replace("_", "1").split("\\s*,\\s*"));
channelTemp.forEach(item -> metaObject.channel.add(Integer.parseInt(item)));
System.out.println("done");
}
Unfortunately, this throws a NullPointerException in the third line here and I don't have a clue why. I replaced _ with 1 for testing purposes to avoid a NumberFormatException. When I print out every object in the lambda function instead of adding them to my ArrayList<Integer>, I can see that all items have an Integer value. So why do I get an exception here?
Since you're almost there I'll give you a hand.
String line = "#KEY,_,0,1,2 , _,4,5,6,";
List<Integer> collect = Arrays.stream(line.replaceAll("#KEY|_", "").split(","))
.map(String::trim)
.filter(s -> !s.isEmpty())
.map(Integer::valueOf).collect(Collectors.toList());
System.out.println(collect);
EDIT
To obtain the null you can alter the mapping process like:
List<Integer> collect = Arrays.stream(line.split(","))
.skip(line.startsWith("#KEY") ? 1 : 0)
.map(String::trim)
.filter(s -> !s.isEmpty())
.map(s -> "_".equals(s) ? null : Integer.valueOf(s)).collect(Collectors.toList());
You're trying to put in list of Integer a String:
metaObject.key1 = Arrays.asList(line.replace("#KEY,", "").replace("_", "").trim().split("\\s*,\\s*"));
Here line.replace(...) and trim() return a String, and split(...) returns a String[].
Therefore Arrays.asList(...) returns a List<String> here, that's not compatible with your definition of key1 (List<Integer>).
Yes, you can convert it to List<Integer> by call Integer.valueOf(...) or Integer.parseInt(...).
But I would recommend to
Use a new instance of List instead of Arrays.asList(...) because the latest one will produce an unmodifiable collection. Sometines it's not what you want :)
Use something less specific than your own text format. What about JSON? There are a lot of libraries to simplify parsing/storing of the data.
Firstly, you should split your string with ",", then you try if your each String is an integer or not with an isIntegerMethod. If it is an integer, you can add it into the list.
public static void main(String[] args) throws IOException {
String str = "#KEY,_,0,1,2,_,4,5,9";
String [] strArr = str.split(",");
List<Integer> intList = new ArrayList<Integer>();
for (String string : strArr) {
if (isInteger(string, 10)) {
intList.add(Integer.valueOf(string));
} else {
System.out.println(string + " is not an integer");
}
}
System.out.println(intList.toString());
}
public static boolean isInteger(String s, int radix) {
if(s.isEmpty()) return false;
for(int i = 0; i < s.length(); i++) {
if(i == 0 && s.charAt(i) == '-') {
if(s.length() == 1) return false;
else continue;
}
if(Character.digit(s.charAt(i),radix) < 0) return false;
}
return true;
}
I was wondering how I could search an ArrayList of Strings to find the most commonly occurring 'destination' in an 'Itinerary' object I've created (which contains a list of different destinations.)
So far I have:
public static String commonName(ArrayList<Itinerary> itinerary){
int count = 0;
int total = 0;
ArrayList<String> names = new ArrayList<String>();
Iterator<String>itr2 = names.iterator();
while(itr.hasNext()){
Itinerary temp = itr.next();
if(temp.iterator().hasNext()){ //if its has destinations
// Destination object in itinerary object
Destination temp2 = temp.iterator().next();
String name = temp2.getDestination().toLowerCase().replace(" ", "");
if(names.contains(name)){
count = count + 1;
//do something with counting the occurence of string name here
}
I'm having problems making an algorithm to search the array for the most commonly occurring string, or strings if there is a tie; and then displaying the number of the 'Itinerary object' (the parameter value) the string is found in. Any help would be great, thank you!!
I would make a HashMap<String,Integer>. Then I would go through each itinerary, and if the destination wans't in the Map I would create an entry with put(destination, 1), otherwise I would increment the count that was there with put(destination, get(destination)+1). Afterwards I'd go through the Map entries and look for the one with the highest count.
If you don't mind using an external jar, you could use HashBag from apache commons to do this easily.
public static String commonName(ArrayList<Itinerary> itinerary){
int count = 0;
int total = 0;
Bag names = new HashBag();
while(itr.hasNext()){ //while array of Itinerary object has next
Itinerary temp = itr.next(); //temp = 1st itineray object
if(temp.iterator().hasNext()){ //if its has destinations
Destination temp2 = temp.iterator().next(); //n Destination object in itinerary object
String name = temp2.getDestination().toLowerCase().replace(" ", "");
names.add(name, 1);
}
}
And then later you can call names.getCount("destination1") to get the number of occurrences of destination1
See http://commons.apache.org/collections/userguide.html#Bags
Try the group feature of the lambdaj library. To solve your problem you could group the Itenarary objects on the destination property and then find the group with the biggest size as in the following example:
Group<Sale> group = selectMax(group(itineraries,
by(on(Itenarary.class).getDestination())).subgroups(), on(Group.class).getSize());
In statistics, this is called the "mode". A vanilla Java 8 solution looks like this:
itinerary
.stream()
.flatMap(i -> StreamSupport.stream(
Spliterators.spliteratorUnknownSize(i.iterator(), 0)
))
.collect(Collectors.groupingBy(
s -> s.getDestination().toLowerCase().replace(" ", ""),
Collectors.counting()
))
.entrySet()
.stream()
.max(Comparator.comparing(Entry::getValue))
.ifPresent(System.out::println);
jOOλ is a library that supports mode() on streams. The following program:
System.out.println(
Seq.seq(itinerary)
.flatMap(i -> Seq.seq(i.iterator()))
.map(s -> s.getDestination().toLowerCase().replace(" ", ""))
.mode()
);
(disclaimer: I work for the company behind jOOλ)