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
Related
The following code (run in android) always gives me a ClassCastException in the 3rd line:
final String[] v1 = i18nCategory.translation.get(id);
final ArrayList<String> v2 = new ArrayList<String>(Arrays.asList(v1));
String[] v3 = (String[])v2.toArray();
It happens also when v2 is Object[0] and also when there are Strings in it.
Any Idea why?
This is because when you use
toArray()
it returns an Object[], which can't be cast to a String[] (even tho the contents are Strings) This is because the toArray method only gets a
List
and not
List<String>
as generics are a source code only thing, and not available at runtime and so it can't determine what type of array to create.
use
toArray(new String[v2.size()]);
which allocates the right kind of array (String[] and of the right size)
You are using the wrong toArray()
Remember that Java's generics are mostly syntactic sugar. An ArrayList doesn't actually know that all its elements are Strings.
To fix your problem, call toArray(T[]). In your case,
String[] v3 = v2.toArray(new String[v2.size()]);
Note that the genericized form toArray(T[]) returns T[], so the result does not need to be explicitly cast.
String[] v3 = v2.toArray(new String[0]);
also does the trick,
note that you don't even need to cast anymore once the right ArrayType is given to the method.
Using toArray from the JDK 11 Stream API, you can solve the more general problem this way:
Object[] v1 = new String[] {"a", "b", "c"}; // or array of another type
String[] v2 = Arrays.stream(v1)
.<String>map((Object v) -> v.toString()).toArray(String[]::new);
String[] str = new String[list.size()];
str = (String[]) list.toArray(str);
Use like this.
I want to know if it is safe/advisable to convert from ArrayList to Array?
I have a text file with each line a string:
1236
1233
4566
4568
....
I want to read them into array list and then i convert it to Array. Is it advisable/legal to do that?
thanks
Yes it is safe to convert an ArrayList to an Array. Whether it is a good idea depends on your intended use. Do you need the operations that ArrayList provides? If so, keep it an ArrayList. Else convert away!
ArrayList<Integer> foo = new ArrayList<Integer>();
foo.add(1);
foo.add(1);
foo.add(2);
foo.add(3);
foo.add(5);
Integer[] bar = foo.toArray(new Integer[foo.size()]);
System.out.println("bar.length = " + bar.length);
outputs
bar.length = 5
This is the best way (IMHO).
List<String> myArrayList = new ArrayList<String>();
//.....
String[] myArray = myArrayList.toArray(new String[myArrayList.size()]);
This code works also:
String[] myArray = myArrayList.toArray(new String[0]);
But it less effective: the string array is created twice: first time zero-length array is created, then the real-size array is created, filled and returned. So, if since you know the needed size (from list.size()) you should create array that is big enough to put all elements. In this case it is not re-allocated.
ArrayList<String> myArrayList = new ArrayList<String>();
...
String[] myArray = myArrayList.toArray(new String[0]);
Whether it's a "good idea" would really be dependent on your use case.
assuming v is a ArrayList:
String[] x = (String[]) v.toArray(new String[0]);
There are two styles to convert a collection to an array: either using a pre-sized array (like c.toArray(new String[c.size()])) or using an empty array (like c.toArray(new String[0])).
In older Java versions using pre-sized array was recommended, as the reflection call which is necessary to create an array of proper size was quite slow. However since late updates of OpenJDK 6 this call was intrinsified, making the performance of the empty array version the same and sometimes even better, compared to the pre-sized version. Also passing pre-sized array is dangerous for a concurrent or synchronized collection as a data race is possible between the size and toArray call which may result in extra nulls at the end of the array, if the collection was concurrently shrunk during the operation.
You can follow the uniform style: either using an empty array (which is recommended in modern Java) or using a pre-sized array (which might be faster in older Java versions or non-HotSpot based JVMs).
This is the recommended usage for newer Java ( >Java 6)
String[] myArray = myArrayList.toArray(new String[0]);
In older Java versions using pre-sized array was recommended, as the
reflection call which is necessary to create an array of proper size
was quite slow. However since late updates of OpenJDK 6 this call was
intrinsified, making the performance of the empty array version the
same and sometimes even better, compared to the pre-sized version.
Also passing pre-sized array is dangerous for a concurrent or
synchronized collection as a data race is possible between the size
and toArray call which may result in extra nulls at the end of the
array, if the collection was concurrently shrunk during the operation.
This inspection allows to follow the uniform style: either using an
empty array (which is recommended in modern Java) or using a pre-sized
array (which might be faster in older Java versions or non-HotSpot
based JVMs).
Most answers work as accepted. But since Java 11, there's another way to use toArray() method using method reference operator or double colon operation (::).
Here's an example:
ArrayList<String> list = new ArrayList<>();
// ... add strings to list
// Since java 11
String[] strArray = list.toArray(String[]::new);
// before java 11, as specified in the official documentation.
strArray = list.toArray(new String[0]);
The Collection interface includes the toArray() method to convert a new collection into an array. There are two forms of this method. The no argument version will return the elements of the collection in an Object array: public Object[ ] toArray(). The returned array cannot cast to any other data type. This is the simplest version. The second version requires you to pass in the data type of the array you’d like to return: public Object [ ] toArray(Object type[ ]).
public static void main(String[] args) {
List<String> l=new ArrayList<String>();
l.add("A");
l.add("B");
l.add("C");
Object arr[]=l.toArray();
for(Object a:arr)
{
String str=(String)a;
System.out.println(str);
}
}
for reference, refer this link http://techno-terminal.blogspot.in/2015/11/how-to-obtain-array-from-arraylist.html
One approach would be to add the Second for Loop where the printing is being done inside the first for loop. Like this:
static String[] SENTENCE;
public static void main(String []args) throws Exception{
Scanner sentence = new Scanner(new File("assets/blah.txt"));
ArrayList<String> sentenceList = new ArrayList<String>();
while (sentence.hasNextLine())
{
sentenceList.add(sentence.nextLine());
}
sentence.close();
String[] sentenceArray = sentenceList.toArray(new String[sentenceList.size()]);
// System.out.println(sentenceArray.length);
for (int r=0;r<sentenceArray.length;r++)
{
SENTENCE = sentenceArray[r].split("(?<=[.!?])\\s*"); //split sentences and store in array
for (int i=0;i<SENTENCE.length;i++)
{
System.out.println("Sentence " + (i+1) + ": " + SENTENCE[i]);
}
}
}
ArrayList<String> a = new ArrayList<String>();
a.add( "test" );
#SuppressWarnings( "unused")
Object[] array = a.toArray();
It depends on what you want to achieve if you need to manipulate the array later it would cost more effort than keeping the string in the ArrayList. You have also random access with an ArrayList by list.get( index );
I usually use this method.
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
int[] arr = list.stream().mapToInt(i -> i).toArray();
System.out.println(Arrays.toString(arr)); // [1, 2, 3]
}
The following code (run in android) always gives me a ClassCastException in the 3rd line:
final String[] v1 = i18nCategory.translation.get(id);
final ArrayList<String> v2 = new ArrayList<String>(Arrays.asList(v1));
String[] v3 = (String[])v2.toArray();
It happens also when v2 is Object[0] and also when there are Strings in it.
Any Idea why?
This is because when you use
toArray()
it returns an Object[], which can't be cast to a String[] (even tho the contents are Strings) This is because the toArray method only gets a
List
and not
List<String>
as generics are a source code only thing, and not available at runtime and so it can't determine what type of array to create.
use
toArray(new String[v2.size()]);
which allocates the right kind of array (String[] and of the right size)
You are using the wrong toArray()
Remember that Java's generics are mostly syntactic sugar. An ArrayList doesn't actually know that all its elements are Strings.
To fix your problem, call toArray(T[]). In your case,
String[] v3 = v2.toArray(new String[v2.size()]);
Note that the genericized form toArray(T[]) returns T[], so the result does not need to be explicitly cast.
String[] v3 = v2.toArray(new String[0]);
also does the trick,
note that you don't even need to cast anymore once the right ArrayType is given to the method.
Using toArray from the JDK 11 Stream API, you can solve the more general problem this way:
Object[] v1 = new String[] {"a", "b", "c"}; // or array of another type
String[] v2 = Arrays.stream(v1)
.<String>map((Object v) -> v.toString()).toArray(String[]::new);
String[] str = new String[list.size()];
str = (String[]) list.toArray(str);
Use like this.
I use the following code to convert an Object array to a String array :
Object Object_Array[]=new Object[100];
// ... get values in the Object_Array
String String_Array[]=new String[Object_Array.length];
for (int i=0;i<String_Array.length;i++) String_Array[i]=Object_Array[i].toString();
But I wonder if there is another way to do this, something like :
String_Array=(String[])Object_Array;
But this would cause a runtime error: Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
What's the correct way to do it ?
Another alternative to System.arraycopy:
String[] stringArray = Arrays.copyOf(objectArray, objectArray.length, String[].class);
In Java 8:
String[] strings = Arrays.stream(objects).toArray(String[]::new);
To convert an array of other types:
String[] strings = Arrays.stream(obj).map(Object::toString).
toArray(String[]::new);
System.arraycopy is probably the most efficient way, but for aesthetics, I'd prefer:
Arrays.asList(Object_Array).toArray(new String[Object_Array.length]);
I see that some solutions have been provided but not any causes so I will explain this in detail as I believe it is as important to know what were you doing wrong that just to get "something" that works from the given replies.
First, let's see what Oracle has to say
* <p>The returned array will be "safe" in that no references to it are
* maintained by this list. (In other words, this method must
* allocate a new array even if this list is backed by an array).
* The caller is thus free to modify the returned array.
It may not look important but as you'll see it is... So what does the following line fail? All object in the list are String but it does not convert them, why?
List<String> tList = new ArrayList<String>();
tList.add("4");
tList.add("5");
String tArray[] = (String[]) tList.toArray();
Probably, many of you would think that this code is doing the same, but it does not.
Object tSObjectArray[] = new String[2];
String tStringArray[] = (String[]) tSObjectArray;
When in reality the written code is doing something like this. The javadoc is saying it! It will instatiate a new array, what it will be of Objects!!!
Object tSObjectArray[] = new Object[2];
String tStringArray[] = (String[]) tSObjectArray;
So tList.toArray is instantiating a Objects and not Strings...
Therefore, the natural solution that has not been mentioning in this thread, but it is what Oracle recommends is the following
String tArray[] = tList.toArray(new String[0]);
Hope it is clear enough.
The google collections framework offers quote a good transform method,so you can transform your Objects into Strings. The only downside is that it has to be from Iterable to Iterable but this is the way I would do it:
Iterable<Object> objects = ....... //Your chosen iterable here
Iterable<String> strings = com.google.common.collect.Iterables.transform(objects, new Function<Object, String>(){
String apply(Object from){
return from.toString();
}
});
This take you away from using arrays,but I think this would be my prefered way.
This one is nice, but doesn't work as mmyers noticed, because of the square brackets:
Arrays.toString(objectArray).split(",")
This one is ugly but works:
Arrays.toString(objectArray).replaceFirst("^\\[", "").replaceFirst("\\]$", "").split(",")
If you use this code you must be sure that the strings returned by your objects' toString() don't contain commas.
If you want to get a String representation of the objects in your array, then yes, there is no other way to do it.
If you know your Object array contains Strings only, you may also do (instread of calling toString()):
for (int i=0;i<String_Array.length;i++) String_Array[i]= (String) Object_Array[i];
The only case when you could use the cast to String[] of the Object_Array would be if the array it references would actually be defined as String[] , e.g. this would work:
Object[] o = new String[10];
String[] s = (String[]) o;
You can use type-converter.
To convert an array of any types to array of strings you can register your own converter:
TypeConverter.registerConverter(Object[].class, String[].class, new Converter<Object[], String[]>() {
#Override
public String[] convert(Object[] source) {
String[] strings = new String[source.length];
for(int i = 0; i < source.length ; i++) {
strings[i] = source[i].toString();
}
return strings;
}
});
and use it
Object[] objects = new Object[] {1, 23.43, true, "text", 'c'};
String[] strings = TypeConverter.convert(objects, String[].class);
For your idea, actually you are approaching the success, but if you do like this should be fine:
for (int i=0;i<String_Array.length;i++) String_Array[i]=(String)Object_Array[i];
BTW, using the Arrays utility method is quite good and make the code elegant.
Object arr3[]=list1.toArray();
String common[]=new String[arr3.length];
for (int i=0;i<arr3.length;i++)
{
common[i]=(String)arr3[i];
}
Easily change without any headche
Convert any object array to string array
Object drivex[] = {1,2};
for(int i=0; i<drive.length ; i++)
{
Str[i]= drivex[i].toString();
System.out.println(Str[i]);
}
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.