Convert List<String> to List<Integer> directly - java

After parsing my file " s" contains AttributeGet:1,16,10106,10111
So I need to get all the numbers after colon in the attributeIDGet List. I know there are several ways to do it. But is there any way we can Directly convert List<String> to List<Integer>.
As the below code complains about Type mismatch, so I tried to do the Integer.parseInt, but I guess this will not work for List. Here s is String.
private static List<Integer> attributeIDGet = new ArrayList<Integer>();
if(s.contains("AttributeGet:")) {
attributeIDGet = Arrays.asList(s.split(":")[1].split(","));
}

Using Java8:
stringList.stream().map(Integer::parseInt).collect(Collectors.toList());

No, you need to loop over the array
for(String s : strList) intList.add(Integer.valueOf(s));

Using lambda:
strList.stream().map(org.apache.commons.lang3.math.NumberUtils::toInt).collect(Collectors.toList());

You can use the Lambda functions of Java 8 to achieve this without looping
String string = "1, 2, 3, 4";
List<Integer> list = Arrays.asList(string.split(",")).stream().map(s -> Integer.parseInt(s.trim())).collect(Collectors.toList());

Guava Converters do the trick.
import com.google.common.base.Splitter;
import com.google.common.primitives.Longs;
final Iterable<Long> longIds =
Longs.stringConverter().convertAll(
Splitter.on(',').trimResults().omitEmptyStrings()
.splitToList("1,2,3"));

No, you will have to iterate over each element:
for(String number : numbers) {
numberList.add(Integer.parseInt(number));
}
The reason this happens is that there is no straightforward way to convert a list of one type into any other type. Some conversions are not possible, or need to be done in a specific way. Essentially the conversion depends on the objects involved and the context of the conversion so there is no "one size fits all" solution. For example, what if you had a Car object and a Person object. You can't convert a List<Car> into a List<Person> directly since it doesn't really make sense.

If you use Google Guava library this is what you can do, see Lists#transform
String s = "AttributeGet:1,16,10106,10111";
List<Integer> attributeIDGet = new ArrayList<Integer>();
if(s.contains("AttributeGet:")) {
List<String> attributeIDGetS = Arrays.asList(s.split(":")[1].split(","));
attributeIDGet =
Lists.transform(attributeIDGetS, new Function<String, Integer>() {
public Integer apply(String e) {
return Integer.parseInt(e);
};
});
}
Yep, agree with above answer that's it's bloated, but stylish. But it's just another way.

Why don't you use stream to convert List of Strings to List of integers?
like below
List<String> stringList = new ArrayList<String>(Arrays.asList("10", "30", "40",
"50", "60", "70"));
List<Integer> integerList = stringList.stream()
.map(Integer::valueOf).collect(Collectors.toList());
complete operation could be something like this
String s = "AttributeGet:1,16,10106,10111";
List<Integer> integerList = (s.startsWith("AttributeGet:")) ?
Arrays.asList(s.replace("AttributeGet:", "").split(","))
.stream().map(Integer::valueOf).collect(Collectors.toList())
: new ArrayList<Integer>();

If you're allowed to use lambdas from Java 8, you can use the following code sample.
final String text = "1:2:3:4:5";
final List<Integer> list = Arrays.asList(text.split(":")).stream()
.map(s -> Integer.parseInt(s))
.collect(Collectors.toList());
System.out.println(list);
No use of external libraries. Plain old new Java!

Using Streams and Lambda:
newIntegerlist = listName.stream().map(x->
Integer.valueOf(x)).collect(Collectors.toList());
The above line of code will convert the List of type List<String> to List<Integer>.
I hope it was helpful.

No, there is no way (that I know of), of doing that in Java.
Basically you'll have to transform each entry from String to Integer.
What you're looking for could be achieved in a more functional language, where you could pass a transformation function and apply it to every element of the list... but such is not possible (it would still apply to every element in the list).
Overkill:
You can, however use a Function from Google Guava (http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Function.html) to simulate a more functional approach, if that is what you're looking for.
If you're worried about iterating over the list twice, then instead of split use a Tokenizer and transform each integer token to Integer before adding to the list.

Here is another example to show power of Guava. Although, this is not the way I write code, I wanted to pack it all together to show what kind of functional programming Guava provides for Java.
Function<String, Integer> strToInt=new Function<String, Integer>() {
public Integer apply(String e) {
return Integer.parseInt(e);
}
};
String s = "AttributeGet:1,16,10106,10111";
List<Integer> attributeIDGet =(s.contains("AttributeGet:"))?
FluentIterable
.from(Iterables.skip(Splitter.on(CharMatcher.anyOf(";,")).split(s)), 1))
.transform(strToInt)
.toImmutableList():
new ArrayList<Integer>();

Use Guava transform method as below,
List intList = Lists.transform(stringList, Integer::parseInt);

import java.util.Arrays;
import java.util.Scanner;
public class reto1 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
double suma = 0, promedio = 0;
String IRCA = "";
int long_vector = Integer.parseInt(input.nextLine());
int[] Lista_Entero = new int[long_vector]; // INSTANCE INTEGER LIST
String[] lista_string = new String[long_vector]; // INSTANCE STRING LIST
Double[] lista_double = new Double[long_vector];
lista_string = input.nextLine().split(" "); // INPUT STRING LIST
input.close();
for (int i = 0; i < long_vector; i++) {
Lista_Entero[i] = Integer.parseInt(lista_string[i]); // CONVERT INDEX TO INDEX FROM STRING UNTIL INTEGER AND ASSIGNED TO NEW INTEGER LIST
suma = suma + Lista_Entero[i];
}

Related

Using streams to convert a list of objects into a string obtained from the toString method

There are a lot of useful new things in Java 8. E.g., I can iterate with a stream over a list of objects and then sum the values from a specific field of the Object's instances. E.g.
public class AClass {
private int value;
public int getValue() { return value; }
}
Integer sum = list.stream().mapToInt(AClass::getValue).sum();
Thus, I'm asking if there is any way to build a String that concatenates the output of the toString() method from the instances in a single line.
List<Integer> list = ...
String concatenated = list.stream().... //concatenate here with toString() method from java.lang.Integer class
Suppose that list contains integers 1, 2 and 3, I expect that concatenated is "123" or "1,2,3".
One simple way is to append your list items in a StringBuilder
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
StringBuilder b = new StringBuilder();
list.forEach(b::append);
System.out.println(b);
you can also try:
String s = list.stream().map(e -> e.toString()).reduce("", String::concat);
Explanation: map converts Integer stream to String stream, then its reduced as concatenation of all the elements.
Note: This is normal reduction which performs in O(n2)
for better performance use a StringBuilder or mutable reduction similar to F. Böller's answer.
String s = list.stream().map(Object::toString).collect(Collectors.joining(","));
Ref: Stream Reduction
There is a collector joining in the API.
It's a static method in Collectors.
list.stream().map(Object::toString).collect(Collectors.joining(","))
Not perfect because of the necessary call of toString, but works. Different delimiters are possible.
Just in case anyone is trying to do this without java 8, there is a pretty good trick. List.toString() already returns a collection that looks like this:
[1,2,3]
Depending on your specific requirements, this can be post-processed to whatever you want as long as your list items don't contain [] or , .
For instance:
list.toString().replace("[","").replace("]","")
or if your data might contain square brackets this:
String s=list.toString();
s = s.substring(1,s.length()-1)
will get you a pretty reasonable output.
One array item on each line can be created like this:
list.toString().replace("[","").replace("]","").replaceAll(",","\r\n")
I used this technique to make html tooltips from a list in a small app, with something like:
list.toString().replace("[","<html>").replace("]","</html>").replaceAll(",","<br>")
If you have an array then start with Arrays.asList(list).toString() instead
I'll totally own the fact that this is not optimal, but it's not as inefficient as you might think and is pretty straightforward to read and understand. It is, however, quite inflexible--in particular don't try to separate the elements with replaceAll if your data might contain commas and use the substring version if you have square brackets in your data, but for an array of numbers it's pretty much perfect.
There is a method in the String API for those "joining list of string" usecases, you don't even need Stream.
List<String> myStringIterable = Arrays.asList("baguette", "bonjour");
String myReducedString = String.join(",", myStringIterable);
// And here you obtain "baguette,bonjour" in your myReducedString variable
The other answers are fine. However, you can also pass Collectors.toList() as parameter to Stream.collect() to return the elements as an ArrayList.
System.out.println( list.stream().map( e -> e.toString() ).collect( toList() ) );
StringListName = ObjectListName.stream().map( m -> m.toString() ).collect( Collectors.toList() );
List<String> list = Arrays.asList("One", "Two", "Three");
list.stream()
.reduce("", org.apache.commons.lang3.StringUtils::join);
Or
List<String> list = Arrays.asList("One", "Two", "Three");
list.stream()
.reduce("", (s1,s2)->s1+s2);
This approach allows you also build a string result from a list of objects
Example
List<Wrapper> list = Arrays.asList(w1, w2, w2);
list.stream()
.map(w->w.getStringValue)
.reduce("", org.apache.commons.lang3.StringUtils::join);
Here the reduce function allows you to have some initial value to which you want to append new string
Example:
List<String> errors = Arrays.asList("er1", "er2", "er3");
list.stream()
.reduce("Found next errors:", (s1,s2)->s1+s2);
Testing both approaches suggested in Shail016 and bpedroso answer (https://stackoverflow.com/a/24883180/2832140), the simple StringBuilder + append(String) within a for loop, seems to execute much faster than list.stream().map([...].
Example: This code walks through a Map<Long, List<Long>> builds a json string, using list.stream().map([...]:
if (mapSize > 0) {
StringBuilder sb = new StringBuilder("[");
for (Map.Entry<Long, List<Long>> entry : threadsMap.entrySet()) {
sb.append("{\"" + entry.getKey().toString() + "\":[");
sb.append(entry.getValue().stream().map(Object::toString).collect(Collectors.joining(",")));
}
sb.delete(sb.length()-2, sb.length());
sb.append("]");
System.out.println(sb.toString());
}
On my dev VM, junit usually takes between 0.35 and 1.2 seconds to execute the test. While, using this following code, it takes between 0.15 and 0.33 seconds:
if (mapSize > 0) {
StringBuilder sb = new StringBuilder("[");
for (Map.Entry<Long, List<Long>> entry : threadsMap.entrySet()) {
sb.append("{\"" + entry.getKey().toString() + "\":[");
for (Long tid : entry.getValue()) {
sb.append(tid.toString() + ", ");
}
sb.delete(sb.length()-2, sb.length());
sb.append("]}, ");
}
sb.delete(sb.length()-2, sb.length());
sb.append("]");
System.out.println(sb.toString());
}
A clean way to do this is by mapping the elements of the list to string and then using the joining operation in Collectors class.
List<Integer> ls = new ArrayList<Integer>();
ls.add(1);
ls.add(2);
ls.add(3);
String s = ls.stream().map(Object::toString).collect(Collectors.joining(","));
String actual = list.stream().reduce((t, u) -> t + "," + u).get();
I'm going to use the streams api to convert a stream of integers into a single string. The problem with some of the provided answers is that they produce a O(n^2) runtime because of String building. A better solution is to use a StringBuilder, and then join the strings together as the final step.
// Create a stream of integers
String result = Arrays.stream(new int[]{1,2,3,4,5,6 })
// collect into a single StringBuilder
.collect(StringBuilder::new, // supplier function
// accumulator - converts cur integer into a string and appends it to the string builder
(builder, cur) -> builder.append(Integer.toString(cur)),
// combiner - combines two string builders if running in parallel
StringBuilder::append)
// convert StringBuilder into a single string
.toString();
You can take this process a step further by converting the collection of object to a single string.
// Start with a class definition
public static class AClass {
private int value;
public int getValue() { return value; }
public AClass(int value) { this.value = value; }
#Override
public String toString() {
return Integer.toString(value);
}
}
// Create a stream of AClass objects
String resultTwo = Arrays.stream(new AClass[]{
new AClass(1),
new AClass(2),
new AClass(3),
new AClass(4)
})
// transform stream of objects into a single string
.collect(StringBuilder::new,
(builder, curObj) -> builder.append(curObj.toString()),
StringBuilder::append
)
// finally transform string builder into a single string
.toString();
Can we try this.
public static void main(String []args){
List<String> stringList = new ArrayList<>();
for(int i=0;i< 10;i++){
stringList.add(""+i);
}
String stringConcated = String.join(",", stringList);
System.out.println(stringConcated);
}
Also, you can do like this.
List<String> list = Arrays.asList("One", "Two", "Three");
String result = String.join(", ", list);
System.out.println(result);
With Java 8+
String s = Arrays.toString(list.stream().toArray(AClass[]::new));
Not the most efficient, but it is a solution with a small amount of code.

Store associative array of strings with length as keys

I have this input:
5
it
your
reality
real
our
First line is number of strings comming after. And i should store it this way (pseudocode):
associative_array = [ 2 => ['it'], 3 => ['our'], 4 => ['real', 'your'], 7 => ['reality']]
As you can see the keys of associative array are the length of strings stored in inner array.
So how can i do this in java ? I came from php world, so if you will compare it with php, it will be very well.
MultiMap<Integer, String> m = new MultiHashMap<Integer, String>();
for(String item : originalCollection) {
m.put(item.length(), item);
}
djechlin already posted a better version, but here's a complete standalone example using just JDK classes:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class Main {
public static void main(String[] args) throws Exception{
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String firstLine = reader.readLine();
int numOfRowsToFollow = Integer.parseInt(firstLine);
Map<Integer,Set<String>> stringsByLength = new HashMap<>(numOfRowsToFollow); //worst-case size
for (int i=0; i<numOfRowsToFollow; i++) {
String line = reader.readLine();
int length = line.length();
Set<String> alreadyUnderThatLength = stringsByLength.get(length); //int boxed to Integer
if (alreadyUnderThatLength==null) {
alreadyUnderThatLength = new HashSet<>();
stringsByLength.put(length, alreadyUnderThatLength);
}
alreadyUnderThatLength.add(line);
}
System.out.println("results: "+stringsByLength);
}
}
its output looks like this:
3
bob
bart
brett
results: {4=[bart], 5=[brett], 3=[bob]}
Java doesn't have associative arrays. But it does have Hashmaps, which mostly accomplishes the same goal. In your case, you can have multiple values for any given key. So what you could do is make each entry in the Hashmap an array or a collection of some kind. ArrayList is a likely choice. That is:
Hashmap<Integer,ArrayList<String>> words=new HashMap<Integer,ArrayList<String>>();
I'm not going to go through the code to read your list from a file or whatever, that's a different question. But just to give you the idea of how the structure would work, suppose we could hard-code the list. We could do it something like this:
ArrayList<String> set=new ArrayList<String)();
set.add("it");
words.put(Integer.valueOf(2), set);
set.clear();
set.add("your");
set.add("real");
words.put(Integer.valueOf(4), set);
Etc.
In practice, you probably would regularly be adding words to an existing set. I often do that like this:
void addWord(String word)
{
Integer key=Integer.valueOf(word.length());
ArrayList<String> set=words.get(key);
if (set==null)
{
set=new ArrayList<String>();
words.put(key,set);
}
// either way we now have a set
set.add(word);
}
Side note: I often see programmers end a block like this by putting "set" back into the Hashmap, i.e. "words.put(key,set)" at the end. This is unnecessary: it's already there. When you get "set" from the Hashmap, you're getting a reference, not a copy, so any updates you make are just "there", you don't have to put it back.
Disclaimer: This code is off the top of my head. No warranties expressed or implied. I haven't written any Java in a while so I may have syntax errors or wrong function names. :-)
As your key appears to be small integer, you could use a list of lists. In this case the simplest solution is to use a MultiMap like
Map<Integer, Set<String>> stringByLength = new LinkedHashMap<>();
for(String s: strings) {
Integer len = s.length();
Set<String> set = stringByLength.get(s);
if(set == null)
stringsByLength.put(len, set = new LinkedHashSet<>());
set.add(s);
}
private HashMap<Integer, List<String>> map = new HashMap<Integer, List<String>>();
void addStringToMap(String s) {
int length = s.length();
if (map.get(length) == null) {
map.put(length, new ArrayList<String>());
}
map.get(length).add(s);
}

Java: Convert List<Integer> to String

How can I convert List<Integer> to String? E.g. If my List<Integer> contains numbers 1 2 and 3 how can it be converted to String = "1,2,3"? Every help will be appreciated.
I think you may use simply List.toString() as below:
List<Integer> intList = new ArrayList<Integer>();
intList.add(1);
intList.add(2);
intList.add(3);
String listString = intList.toString();
System.out.println(listString); //<- this prints [1, 2, 3]
If you don't want [] in the string, simply use the substring e.g.:
listString = listString.substring(1, listString.length()-1);
System.out.println(listString); //<- this prints 1, 2, 3
Please note: List.toString() uses AbstractCollection#toString method, which converts the list into String as above
In vanilla Java 8 (streams) you can do
// Given numberList is a List<Integer> of 1,2,3...
String numberString = numberList.stream().map(String::valueOf)
.collect(Collectors.joining(","));
// numberString here is "1,2,3"
With Guava:
String s = Joiner.on(',').join(integerList);
One way would be:
Iterate over list, add each item to StringBuffer (or) StringBuilder and do toString() at end.
Example:
StringBuilder strbul = new StringBuilder();
Iterator<Integer> iter = list.iterator();
while(iter.hasNext())
{
strbul.append(iter.next());
if(iter.hasNext()){
strbul.append(",");
}
}
strbul.toString();
Just to add another (of many) options from a popular library (Apache Commons):
import org.apache.commons.lang3.StringUtils;
String joinedList = StringUtils.join(someList, ",");
See documentation: https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html#join-java.lang.Iterable-java.lang.String-
An elegant option from others' comments (as of Java 8):
String joinedList = someList.stream().map(String::valueOf).collect(Collectors.joining(","));

Is it possible to avoid loop which will cast one object type to another in split() or Arrays.asList()?

I'm trying to simplify my code and I have a question: is it's possible to convert string of IDs separated by coma to specific collection type?
So, my code now is:
String [] condition_list_id_tmp = rule.getContractRuleConditions().split(",");
List<String> condition_list_id = Arrays.asList(condition_list_id_tmp);
List<Long> condition_ids = new ArrayList<Long>();
for (String str_id : condition_list_id){
condition_ids.add(Long.parseLong(str_id));
}
Can I simplify this code by using for example Type collectionType = new TypeToken<List<Long>>() {}.getType(); like in gson?
Have you considered LambdaJ?
class StringToLong implements Converter<String, Long> {
public Long convert(String str) {
return Long.parseLong(str);
}
}
String [] condition_list_id_tmp = rule.getContractRuleConditions().split(",");
List<String> condition_list_id = Arrays.asList(condition_list_id_tmp);
List<Long> condition_ids = convert(condition_list_id, new StringToLong());
or using some libraries, like guava? so that there is no looping in your codes (but in theirs) ?
I saw that your mentioned your goal is "to simplify my code"
e.g.
final List<String> strList = Arrays.asList("1,2,3,4,5".split(","));
final List<Long> l = Lists.transform(strList, new Function<String, Long>() {
#Override
public Long apply(final String input) {
return Long.parseLong(input);
}
});
I don't think so with out looping you can do this. How come your collection's content type be changed with out casting explicitly .
There is no method available without looping. Even if a method is available it will look like to you as a single operation but obviously it has to
loop internally.
For eg: Arrays.fill(arrayname, intval);
This is a single method to fill the array with any integer value. But internally it will also run a loop on the array.
java 8 can do this :
String [] condition_list_id_tmp = rule.getContractRuleConditions().split(",");
List<String> condition_list_id = Arrays.asList(condition_list_id_tmp);
List<Long> condition_ids = condition_list_id.map(c -> Long.parseLong(c))
The solution for your problem until Java 8 pop to the market could be project Guava, with their support for Functional Idioms.
Then you could perform that operation in different way, but as i wrote in the comment. At the end you will have same operation.
public static List<Long> splitToLong(String list, String token) {
StringTokenizer tokenizer= new StringTokenizer(list, token);
List<Long> result = new ArrayList<Long>();
while(tokenizer.hasMoreTokens() {
result.add(Long.parseLong(tokenizer.nextToken()));
}
}
If you put this method in some Util class, then you can enjoy clean code
//....
for(Long mLong : StringHelper.splitToLong(message,",")) {
//Do something with mLong
}
//....

Decompose a String into Array of Long or List of Long without Loop in JAVA

I want to decompose a String array into Long array or List.
I don't want to use Loop.
Is there any Java Method to do this.
Simplified Eugene answer with Guava library. Since Guava 16.0.
List<Long> longList = Lists.transform(Arrays.asList(stringArray), Longs.stringConverter());
Update: Solution with Java 8, without 3th party libraries:
List<Long> longList = Stream.of(stringArray).map(Long::valueOf).collect(Collectors.toList());
There is no O(1) operation to "convert" a String[] (with numeric strings) to a long[]. It will always be O(n), if the loop visible or hidden in some thirdparty method.
If you don't want to "see" the loop, simply implement a method
Long[] pseudoOneStepConversion(numbers);
and implement
privat Long[] pseudoOneStepConversion(String[] numbers) {
Long[] result = new long[numbers.length];
for (int i = 0; i < numbers.length; i++)
result[i] = Long.parseLong(numbers[i]);
return result;
}
We can do it recursively too - it is still O(n), less performant and doesn't look like a loop:
public static void main(String[] args) {
List<Long> target = new ArrayList<Long>();
copy(new String[]{"1", "2", "3"}, target, 0);
System.out.println(target);
}
private static void copy(String[] source, List<Long> target, int index) {
if (index == source.length)
return;
target.add(Long.parseLong(source[index]));
copy(source, target, index+1);
}
Note - because I start getting downvotes for the recursion example: It is purely academic and not inteded for use in production code - thought, that was clear ;)
With a little help of 3rd party libraries you can avoid coding loops in your own code, but there would be a loop somewhere under the hood. For example:
List<String> stringList = Arrays.asList(stringArray);
List<Long> longList = Lists.transform(stringList, new Function<String, Long>() {
public Long apply(String s) {
return Long.valueOf(s);
}
});
Classes Lists and Function are from Guava library.
No there is no way to do this without a loop (even if you don't code explicitly a loop, the method you will call will use one), unless you now the number of long values contained in the String and add them manually to your List.
Your best option is Guavas Lists.transform function.
String[] stringArray = {"1999", "20000"};
List<String> stringList = Arrays.asList(stringArray);
List<Long> longList = Lists.transform(stringList,
new Function<String, Long>() {
Long apply(String value) {
return Long.valueOf(value);
}
});
Note: Guava will of course have to do a loop to achieve this, but there are no loops in your code.
Split String value with comma and Converting String Array to Wrapper Long Array / Primitive long array using Java 8.
String values = "2846, 4514, 8495, 4587, 5772, 3813, 6947, 3186";
Long[] longArray = Arrays.stream(values.split(","))
.map(String::trim)
.map(Long::valueOf)
.toArray(Long[]::new);//Converting String array to Long array
long[] longPrimitiveArray = Arrays.stream(values.split(","))
.map(String::trim)
.mapToLong(Long::valueOf)
.toArray();//Converting String array to long array

Categories