I have a list of integers, List<Integer> and I'd like to convert all the integer objects into Strings, thus finishing up with a new List<String>.
Naturally, I could create a new List<String> and loop through the list calling String.valueOf() for each integer, but I was wondering if there was a better (read: more automatic) way of doing it?
Using Google Collections from Guava-Project, you could use the transform method in the Lists class
import com.google.common.collect.Lists;
import com.google.common.base.Functions
List<Integer> integers = Arrays.asList(1, 2, 3, 4);
List<String> strings = Lists.transform(integers, Functions.toStringFunction());
The List returned by transform is a view on the backing list - the transformation will be applied on each access to the transformed list.
Be aware that Functions.toStringFunction() will throw a NullPointerException when applied to null, so only use it if you are sure your list will not contain null.
Solution for Java 8. A bit longer than the Guava one, but at least you don't have to install a library.
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
//...
List<Integer> integers = Arrays.asList(1, 2, 3, 4);
List<String> strings = integers.stream().map(Object::toString)
.collect(Collectors.toList());
For Java 11,
List<String> strings = integers.stream().map(Object::toString)
.collect(Collectors.toUnmodifiableList());
Still no map convenience method, really?
As far as I know, iterate and instantiate is the only way to do this. Something like (for others potential help, since I'm sure you know how to do this):
List<Integer> oldList = ...
/* Specify the size of the list up front to prevent resizing. */
List<String> newList = new ArrayList<>(oldList.size());
for (Integer myInt : oldList) {
newList.add(String.valueOf(myInt));
}
What you're doing is fine, but if you feel the need to 'Java-it-up' you could use a Transformer and the collect method from Apache Commons, e.g.:
public class IntegerToStringTransformer implements Transformer<Integer, String> {
public String transform(final Integer i) {
return (i == null ? null : i.toString());
}
}
..and then..
CollectionUtils.collect(
collectionOfIntegers,
new IntegerToStringTransformer(),
newCollectionOfStrings);
The source for String.valueOf shows this:
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
Not that it matters much, but I would use toString.
Instead of using String.valueOf I'd use .toString(); it avoids some of the auto boxing described by #johnathan.holland
The javadoc says that valueOf returns the same thing as Integer.toString().
List<Integer> oldList = ...
List<String> newList = new ArrayList<String>(oldList.size());
for (Integer myInt : oldList) {
newList.add(myInt.toString());
}
Here's a one-liner solution without cheating with a non-JDK library.
List<String> strings = Arrays.asList(list.toString().replaceAll("\\[(.*)\\]", "$1").split(", "));
Another Solution using Guava and Java 8
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<String> strings = Lists.transform(numbers, number -> String.valueOf(number));
To the people concerned about "boxing" in jsight's answer: there is none. String.valueOf(Object) is used here, and no unboxing to int is ever performed.
Whether you use Integer.toString() or String.valueOf(Object) depends on how you want to handle possible nulls. Do you want to throw an exception (probably), or have "null" Strings in your list (maybe). If the former, do you want to throw a NullPointerException or some other type?
Also, one small flaw in jsight's response: List is an interface, you can't use the new operator on it. I would probably use a java.util.ArrayList in this case, especially since we know up front how long the list is likely to be.
List<String> stringList = integerList.stream().map((Object s)->String.valueOf(s)).collect(Collectors.toList())
Not core Java, and not generic-ified, but the popular Jakarta commons collections library has some useful abstractions for this sort of task. Specifically, have a look at the collect methods on
CollectionUtils
Something to consider if you are already using commons collections in your project.
A slightly more concise solution using the forEach method on the original list:
List<Integer> oldList = Arrays.asList(1, 2, 3, 4, 5);
List<String> newList = new ArrayList<>(oldList.size());
oldList.forEach(e -> newList.add(String.valueOf(e)));
#Jonathan: I could be mistaken, but I believe that String.valueOf() in this case will call the String.valueOf(Object) function rather than getting boxed to String.valueOf(int). String.valueOf(Object) just returns "null" if it is null or calls Object.toString() if non-null, which shouldn't involve boxing (although obviously instantiating new string objects is involved).
I think using Object.toString() for any purpose other than debugging is probably a really bad idea, even though in this case the two are functionally equivalent (assuming the list has no nulls). Developers are free to change the behavior of any toString() method without any warning, including the toString() methods of any classes in the standard library.
Don't even worry about the performance problems caused by the boxing/unboxing process. If performance is critical, just use an array. If it's really critical, don't use Java. Trying to outsmart the JVM will only lead to heartache.
An answer for experts only:
List<Integer> ints = ...;
String all = new ArrayList<Integer>(ints).toString();
String[] split = all.substring(1, all.length()-1).split(", ");
List<String> strs = Arrays.asList(split);
Lambdaj allows to do that in a very simple and readable way. For example, supposing you have a list of Integer and you want to convert them in the corresponding String representation you could write something like that;
List<Integer> ints = asList(1, 2, 3, 4);
Iterator<String> stringIterator = convertIterator(ints, new Converter<Integer, String> {
public String convert(Integer i) { return Integer.toString(i); }
}
Lambdaj applies the conversion function only while you're iterating on the result.
You can't avoid the "boxing overhead"; Java's faux generic containers can only store Objects, so your ints must be boxed into Integers. In principle it could avoid the downcast from Object to Integer (since it's pointless, because Object is good enough for both String.valueOf and Object.toString) but I don't know if the compiler is smart enough to do that. The conversion from String to Object should be more or less a no-op, so I would be disinclined to worry about that one.
Just for fun, a solution using the jsr166y fork-join framework that should in JDK7.
import java.util.concurrent.forkjoin.*;
private final ForkJoinExecutor executor = new ForkJoinPool();
...
List<Integer> ints = ...;
List<String> strs =
ParallelArray.create(ints.size(), Integer.class, executor)
.withMapping(new Ops.Op<Integer,String>() { public String op(Integer i) {
return String.valueOf(i);
}})
.all()
.asList();
(Disclaimer: Not compiled. Spec is not finalised. Etc.)
Unlikely to be in JDK7 is a bit of type inference and syntactical sugar to make that withMapping call less verbose:
.withMapping(#(Integer i) String.valueOf(i))
This is such a basic thing to do I wouldn't use an external library (it will cause a dependency in your project that you probably don't need).
We have a class of static methods specifically crafted to do these sort of jobs. Because the code for this is so simple we let Hotspot do the optimization for us. This seems to be a theme in my code recently: write very simple (straightforward) code and let Hotspot do its magic. We rarely have performance issues around code like this - when a new VM version comes along you get all the extra speed benefits etc.
As much as I love Jakarta collections, they don't support Generics and use 1.4 as the LCD. I am wary of Google Collections because they are listed as Alpha support level!
I didn't see any solution which is following the principal of space
complexity. If list of integers has large number of elements then it's
big problem.
It will be really good to remove the integer from the List<Integer> and free
the space, once it's added to List<String>.
We can use iterator to achieve the same.
List<Integer> oldList = new ArrayList<>();
oldList.add(12);
oldList.add(14);
.......
.......
List<String> newList = new ArrayList<String>(oldList.size());
Iterator<Integer> itr = oldList.iterator();
while(itr.hasNext()){
newList.add(itr.next().toString());
itr.remove();
}
I just wanted to chime in with an object oriented solution to the problem.
If you model domain objects, then the solution is in the domain objects. The domain here is a List of integers for which we want string values.
The easiest way would be to not convert the list at all.
That being said, in order to convert without converting, change the original list of Integer to List of Value, where Value looks something like this...
class Value {
Integer value;
public Integer getInt()
{
return value;
}
public String getString()
{
return String.valueOf(value);
}
}
This will be faster and take up less memory than copying the List.
Related
I have a list of object :
List<Object[]> list = new ArrayList<>();
Object[] object = {"test", "test1", "test2"};
list.add(object);
List contains some data.
I have another string String str = "test";
I am using below code. What are best other ways:
for (Object []object1 : list) {
for (Object obj : object1) {
if (obj.equals("test")) {
System.out.println("true");
}
}
}
How to check this string present in above list with minimum of code.
Java 8 introduced Streams which are powerful, yet code-compact as you demanded. This answer uses more features of Java 8 sucha as Lambdas and Method References.
Here is a one-liner instruction:
boolean containsObject = list.stream().flatMap(Arrays::stream).filter(s->str.equals(s) ).findFirst().isPresent();
Here how it works:
boolean containsObject = list.stream() // Turning the List into a Stream of Arrays
.flatMap(Arrays::stream) // flattening the 2D structure into a single-dimensional stream of Objects (Note: using a Method reference)
.filter(s->str.equals(s)) // Filtering the flat stream to check for equality (Note: using a Lambda expression)
.findFirst() // Demands to find the first Occurence that passed the Filter test
.isPresent(); // Collapse the stream and returns the result of the above demand (Note: the Stream makes no computation until this instruction)
This solution is code-compact, and brings the nice features of Streams such as parallelization and laziness.
If you convert the Object[]s to lists, then you can call their contains(Object). You could either have list be a List<List<Object>>, or you could leave it with Object[] and wrap the Object[]s in a List as-needed.
Example of the "convert as needed":
for(Object[] object1 : list)
if(Arrays.asList(object1).contains("test"))
System.out.println("true");
Personally, I would have list be a List<List>. Whenever you add to it, just wrap your arrays in a list. Assuming arr is an Object[], that means list.add(Arrays.asList(arr));.
Alexander's answer is also correct (I think; I didn't examine it too closely), but I find long strings of stream operators to be less readable. If you disagree with my opinion on that, then use the stream operators.
What it comes down to is I'm attempting to construct a List<T> from the java.util.List package based on an enumerator, but here's the catch- I don't want the first value to be in the list. The way that I've come up with doing this... Well... It can't be a good thing.
Here's the code I'm using:
Arrays.asList(Arrays.asList(MyEnum.values()).remove(0));
This effectively creates a List<> from my enum, and removes the first value, then tries to create another list with the created list.
This may actually be the correct way to do it, but just looking at it is screaming "Inefficient". I showed it to a few people on a forum that I'm a member of and they all said how ugly it was, and laughed; However not a single one of them could/would provide a better way to go about doing it.
I don't think that code is really ugly or inefficient. The bigger problem is it doesn't work because the list returned by Arrays.asList is backed by the underlying array, and so it has a fixed size.
You can use subList instead of remove to get it working:
List<MyEnum> list = Arrays.asList(MyEnum.values());
list = list.subList(1, list.size());
This means that the resulting list actually consists of two list objects (the asList and its subList), which may or may not bother you. However, you can create a flat ArrayList from the resulting list:
list = new ArrayList<>(list);
If you'd rather minimize object allocation, loop the values and add them to a single list directly:
MyEnum[] values = MyEnum.values();
List<MyEnum> list = new ArrayList<>(values.length - 1);
for (int i = 1; i < values.length; i++)
list.add(values[i]);
How about:
Arrays.asList(MyEnum.values()).subList(1, MyEnum.values().length);
Are you sure you can't (wouldn't want to) use MyEnum.values and treat your first element differently where it's used?
public enum Enums {
first,
b,
c,
d,
e,
f;
public boolean isFirst(Enums e) {
return e == first;
}
}
This would work:
List<T> enums = Arrays.asList(Arrays.copyOfRange(MyEnum.values(), 1, MyEnum.values().length - 1));
Or java 8:
Arrays.stream(MyEnum.values()).collect(Collectors.toList()).subList(1, MyEnum.values() - 1);
Hmmm... not much better .
I have a String arraylist and i am going to convert it to a double arraylist. Is there any way except using loops like for,While to convert it?
ArrayList<String> S=new ArrayList<String>();
S=FillTheList();
ArrayList<Double> D=new ArrayList<Double>();
In the JDK proper, up to version 7, no. JDK 8 will have functional programming support, though (see comment by #JBNizet below for the syntax).
You can use Guava to achieve this however:
final Function<String, Double> fn = new Function<String, Double>()
{
#Override
public Double apply(final String input)
{
return Double.parseDouble(input);
}
};
// with S the original ArrayList<String>
final List<Double> D = Lists.transform(S, fn);
Note that while there is no loop in this code, internally the code will use loops anyway.
More to the point of your original question however, you cannot cast a String to a Double, since these are two different classes. You have to go through a parsing method like shown above.
Assuming you actually want your ArrayList to contain Doubles when you're done, no, there's no alternative, you're going to have to loop through, converting each String to a Double and adding the Double to the new ArrayList.
Note that at runtime, Java doesn't actually know the type that a List contains - it doesn't know that it's an ArrayList<Double>, it just knows that it's an ArrayList. There's therefore no way for the JVM to know what operation needs to happen to convert the contents of your ArrayList<String> (which it also sees as ArrayList) and add them to your ArrayList<Double>.
I have an Array of primitives, for example for int, int[] foo. It might be a small sized one, or not.
int foo[] = {1,2,3,4,5,6,7,8,9,0};
What is the best way to create an Iterable<Integer> from it?
Iterable<Integer> fooBar = convert(foo);
Notes:
Please do not answer using loops (unless you can give a good explanation on how the compiler do something smart about them?)
Also note that
int a[] = {1,2,3};
List<Integer> l = Arrays.asList(a);
Will not even compile
Type mismatch: cannot convert from List<int[]> to List<Integer>
Also check
Why is an array not assignable to Iterable?
before answering.
Also, if you use some library (e.g., Guava), please explain why this is the Best. ( Because its from Google is not a complete answer :P )
Last, since there seems to be a homework about that, avoid posting homeworkish code.
Integer foo[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
List<Integer> list = Arrays.asList(foo);
// or
Iterable<Integer> iterable = Arrays.asList(foo);
Though you need to use an Integer array (not an int array) for this to work.
For primitives, you can use guava:
Iterable<Integer> fooBar = Ints.asList(foo);
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>15.0</version>
<type>jar</type>
</dependency>
For Java8 with lambdas: (Inspired by Jin Kwon's answer)
final int[] arr = { 1, 2, 3 };
final Iterable<Integer> i1 = () -> Arrays.stream(arr).iterator();
final Iterable<Integer> i2 = () -> IntStream.of(arr).iterator();
final Iterable<Integer> i3 = () -> IntStream.of(arr).boxed().iterator();
just my 2 cents:
final int a[] = {1,2,3};
java.lang.Iterable<Integer> aIterable=new Iterable<Integer>() {
public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
private int pos=0;
public boolean hasNext() {
return a.length>pos;
}
public Integer next() {
return a[pos++];
}
public void remove() {
throw new UnsupportedOperationException("Cannot remove an element of an array.");
}
};
}
};
With Java 8, you can do this.
final int[] arr = {1, 2, 3};
final PrimitiveIterator.OfInt i1 = Arrays.stream(arr).iterator();
final PrimitiveIterator.OfInt i2 = IntStream.of(arr).iterator();
final Iterator<Integer> i3 = IntStream.of(arr).boxed().iterator();
Guava provides the adapter you want as Int.asList(). There is an equivalent for each primitive type in the associated class, e.g., Booleans for boolean, etc.
int foo[] = {1,2,3,4,5,6,7,8,9,0};
Iterable<Integer> fooBar = Ints.asList(foo);
for(Integer i : fooBar) {
System.out.println(i);
}
The suggestions above to use Arrays.asList won't work, even if they compile because you get an Iterator<int[]> rather than Iterator<Integer>. What happens is that rather than creating a list backed by your array, you created a 1-element list of arrays, containing your array.
In Java 8 or later, Iterable is a functional interface returns Iterator.
So you can do this.
static Iterable<Integer> convert(int[] array) {
return () -> Arrays.stream(array).iterator();
}
and
int[] array = {1, 2, 3};
Iterable<Integer> iterable = convert(array);
for (int i : iterable)
System.out.println(i);
output:
1
2
3
I had the same problem and solved it like this:
final YourType[] yourArray = ...;
return new Iterable<YourType>() {
public Iterator<YourType> iterator() {
return Iterators.forArray(yourArray); // Iterators is a Google guava utility
}
}
The iterator itself is a lazy UnmodifiableIterator but that's exactly what I needed.
First of all, I can only agree that Arrays.asList(T...) is clearly the best solution for Wrapper types or arrays with non-primtive datatypes. This method calls a constructor of a simple private static AbstractList implementation in the Arrays class which basically saves the given array reference as field and simulates a list by overriding the needed methods.
If you can choose between a primtive type or a Wrapper type for your array, I would use the Wrapper type for such situations but of course, it's not always useful or required.
There would be only two possibilities you can do:
1) You can create a class with a static method for each primitive datatype array (boolean, byte, short, int, long, char, float, double returning an Iterable<WrapperType>. These methods would use anonymous classes of Iterator (besides Iterable) which are allowed to contain the reference of the comprising method's argument (for example an int[]) as field in order to implement the methods.
-> This approach is performant and saves you memory (except for the memory of the newly created methods, even though, using Arrays.asList() would take memory in the same way)
2) Since arrays don't have methods (as to be read on the side you linked) they can't provide an Iterator instance either. If you really are too lazy to write new classes, you must use an instance of an already existing class that implements Iterable because there is no other way around than instantiating Iterable or a subtype.
The ONLY way to create an existing Collection derivative implementing Iterable is to use a loop (except you use anonymous classes as described above) or you instantiate an Iterable implementing class whose constructor allows a primtive type array (because Object[] doesn't allow arrays with primitive type elements) but as far as I know, the Java API doesn't feature a class like that.The reason for the loop can be explained easily:for each Collection you need Objects and primtive datatypes aren't objects. Objects are much bigger than primitive types so that they require additional data which must be generated for each element of the primitive type array. That means if two ways of three (using Arrays.asList(T...) or using an existing Collection) require an aggregate of objects, you need to create for each primitive value of your int[] array the wrapper object. The third way would use the array as is and use it in an anonymous class as I think it's preferable due to fast performance.
There is also a third strategy using an Object as argument for the method where you want to use the array or Iterable and it would require type checks to figure out which type the argument has, however I wouldn't recommend it at all as you usually need to consider that the Object hasn't always the required type and that you need seperate code for certain cases.
In conclusion, it's the fault of Java's problematic Generic Type system which doesn't allow to use primitive types as generic type which would save a lot of code by using simply Arrays.asList(T...). So you need to program for each primitive type array, you need, such a method (which basically makes no difference to the memory used by a C++ program which would create for each used type argument a seperate method.
You can use IterableOf from Cactoos:
Iterable<String> names = new IterableOf<>(
"Scott Fitzgerald", "Fyodor Dostoyevsky"
);
Then, you can turn it into a list using ListOf:
List<String> names = new ListOf<>(
new IterableOf<>(
"Scott Fitzgerald", "Fyodor Dostoyevsky"
)
);
Or simply this:
List<String> names = new ListOf<>(
"Scott Fitzgerald", "Fyodor Dostoyevsky"
);
While a similar answer has already been sort of posted, I think the reason to use the new PrimitiveIterator.OfInt was not clear. A good solution is to use Java 8 PrimitiveIterator since it's specialized for primitive int types (and avoids the extra boxing/unboxing penalty):
int[] arr = {1,2,3};
// If you use Iterator<Integer> here as type then you can't get the actual benefit of being able to use nextInt() later
PrimitiveIterator.OfInt iterator = Arrays.stream(arr).iterator();
while (iterator.hasNext()) {
System.out.println(iterator.nextInt());
// Use nextInt() instead of next() here to avoid extra boxing penalty
}
Ref: https://doc.bccnsoft.com/docs/jdk8u12-docs/api/java/util/PrimitiveIterator.OfInt.html
In java8 IntSteam stream can be boxed to stream of Integers.
public static Iterable<Integer> toIterable(int[] ints) {
return IntStream.of(ints).boxed().collect(Collectors.toList());
}
I think performance matters based on the size of the array.
I need to get a String[] out of a Set<String>, but I don't know how to do it. The following fails:
Map<String, ?> myMap = gpxlist.getAll();
Set<String> myset = myMap.keySet();
String[] GPXFILES1 = (String[]) myset.toArray(); // Here it fails.
How can I fix it so that it works?
Use the Set#toArray(IntFunction<T[]>) method taking an IntFunction as generator.
String[] GPXFILES1 = myset.toArray(String[]::new);
If you're not on Java 11 yet, then use the Set#toArray(T[]) method taking a typed array argument of the same size.
String[] GPXFILES1 = myset.toArray(new String[myset.size()]);
While still not on Java 11, and you can't guarantee that myset is unmodifiable at the moment of conversion to array, then better specify an empty typed array.
String[] GPXFILES1 = myset.toArray(new String[0]);
Java 11
The new default toArray method in Collection interface allows the elements of the collection to be transferred to a newly created array of the desired runtime type. It takes IntFunction<T[]> generator as argument and can be used as:
String[] array = set.toArray(String[]::new);
There is already a similar method Collection.toArray(T[]) and this addition means we no longer be able to pass null as argument because in that case reference to the method would be ambiguous. But it is still okay since both methods throw a NPE anyways.
Java 8
In Java 8 we can use streams API:
String[] array = set.stream().toArray(String[]::new);
We can also make use of the overloaded version of toArray() which takes IntFunction<A[]> generator as:
String[] array = set.stream().toArray(n -> new String[n]);
The purpose of the generator function here is to take an integer (size of desired array) and produce an array of desired size. I personally prefer the former approach using method reference than the later one using lambda expression.
Use toArray(T[] a) method:
String[] array = set.toArray(new String[0]);
Guava style:
Set<String> myset = myMap.keySet();
FluentIterable.from(mySet).toArray(String.class);
more info: https://google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/FluentIterable.html
In Java 11 we can use Collection.toArray(generator) method. The following code will create a new array of String:
Set<String> set = Set.of("one", "two", "three");
String[] array = set.toArray(String[]::new)
See: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Collection.html#toArray(java.util.function.IntFunction)
Set<String> stringSet= new HashSet<>();
String[] s = (String[])stringSet.toArray();
I was facing the same situation.
I begin by declaring the structures I need:
Set<String> myKeysInSet = null;
String[] myArrayOfString = null;
In my case, I have a JSON object and I need all the keys in this JSON to be stored in an array of strings. Using the GSON library, I use JSON.keySet() to get the keys and move to my Set :
myKeysInSet = json_any.keySet();
With this, I have a Set structure with all the keys, as I needed it. So I just need to the values to my Array of Strings. See the code below:
myArrayOfString = myKeysInSet.toArray(new String[myKeysInSet.size()]);
This was my first answer in StackOverflow.
Sorry for any error :D