Best way to remove null values from string array - java

Below are the 2 ways to remove null values, which one is the best approach?
public static String[] clean(final String[] v) {
List<String> list = new ArrayList<String>(Arrays.asList(v));
list.removeAll(Collections.singleton(null));
return list.toArray(new String[list.size()]);
}
public static String[] clean(final String[] v) {
List<String> list = new ArrayList<String>(v.length);
for (String aString : v)
{
if (aString != null)
{
list.add(aString);
}
}
return list.toArray(new String[list.size()]);
}

For removing null values from a single string, I would use a regular expression like this,
private static Pattern pattern = Pattern.compile("(?i)[(\\[{]?null[)\\]}]?");
public static String removeNullString(String value) {
if (StringUtils.isEmpty(value)) {
return StringUtils.EMPTY;
}
Matcher matcher = pattern.matcher(value);
return matcher.replaceAll(StringUtils.EMPTY);
}
It covers up all "null" and empty character from string.
For removing null value from a string array in Java 7,
String[] firstArray = {"test1", "", "test2", "test4", "", null};
List<String> list = new ArrayList<String>();
for(String s : firstArray) {
if(s != null && s.length() > 0) {
list.add(s);
}
}
firstArray = list.toArray(new String[list.size()]);
For removing null value from a string array in Java 8,
String[] firstArray = {"test1", "", "test2", "test4", "", null};
firstArray = Arrays.stream(firstArray)
.filter(s -> (s != null && s.length() > 0))
.toArray(String[]::new);

Performance wise, it is usually better to minimize calls outside of the scope of the current code block (ie method). Also, since memory allocation is relatively slow compared most other instructions, avoiding object creation is typically a goal. The best I can come up with in terms of performance (I chose to make it flexible enough to take any type of array):
public <T> T[] removeNulls(Class<T> type, final T[] original){
// first, shift all non-null instances to the head, all nulls to the end.
int nonNullCount=0;
T tempT = null;
for(int i=0; i < original.length; i++){
if(original[i] != null){
nonNullCount++;
}else if(i != original.length - 1){
// Swap the next non-null value with this null value
int j = i + 1;
// In case there are multiple null values in a row
// scan ahead until we find the next non-null value
while(j < original.length && (tempT = original[j]) == null){
j++;
}
original[nonNullCount] = tempT;
if(tempT != null){
nonNullCount++;
}
if(j < original.length){
original[j] = null;
}
i = j - 1;
}
}
// The case where there are no nulls in the array
if(nonNullCount == original.length){
return original;
}
final T[] noNulls = (T[]) Array.newInstance(type,nonNullCount);
System.arraycopy(original,0,noNulls,0,nonNullCount);
return noNulls;
}
But I'm not sure why you would want this complexity over the 3 or 4 lines to do the same thing when performance is not likely to be an issue. You would need to have HUGE arrays to see any benefit (if any) between my code and your clean example.

in Java 8 you should be able to do something like:
List<String> list = new ArrayList<String>(Arrays.asList(v));
list.removeIf(Objects::isNull);
return list.toArray(new String[list.size()]);

if you want to do it in same space i will suggest the follwing solution. But final array will also be having same size. I mean it will not shrink in size but all elements will get aggregated in same order.
public static void removeNullFromArray(String[] args) {
int location = 0;
for(int i=0; i<args.length; i++){
String arg = args[i];
if(arg!=null){
if(location<i){
args[location] = arg;
args[i] = null;
}
location++;
}
}
}

Java 8 code using streams and lambda. Filters non-nulls from an array and converts to a list.
Arrays.stream(arr).filter(Objects::nonNull).collect(Collectors.toList());

Related

Multiple arrays stored in one Variable. [Java]

I have multiple arrays stored in one variable each of them is size 1. I'm trying to combine all of them into one single array. I've used Buffered reader to read a csv file and then split it into an arraylist using the following method:
public static ArrayListcsvToArray(String csvData){
ArrayList result = new ArrayList();
if (csvData != null){
String[] splitData = csvData.split(",");
for(int i = 0; i < splitData.length; i++){
if(!(splitData[i] == null) || !(splitData[i].length() == 0)) {
result.add(splitData[i].trim());
}
}
}
return result;
}
The method splits each line of the csv into an arraylist of its own. I want to combine all elements at for example result.get(5) into an arraylist of their own.
Any ideas?
So the idea is to have a parent ArrayList of ArrayList. Every time you call the function, pass along the reference to previous results so they can be consolidated. This is just one out of many ways this can be achieved, but should give you a starting point to optimize further.
// Initialize and provide dummy input.
int requiredIndex = 5;
ArrayList<String> results = new ArrayList<String>();
csvToArray("some,column,data,with,seven,columns,only", results, requiredIndex);
csvToArray("more,data,that,came, in, just, now , and is, longer", results, requiredIndex);
csvToArray("a, short, line", results, requiredIndex);
csvToArray("last, line, of, input, which, is, correct.", results, requiredIndex);
System.out.println(results);
// output : [columns, just, is]
// Update the method as below.
public static void csvToArray(String csvData, ArrayList<String> results, int index){
if (csvData != null){
String[] splitData = csvData.split(",");
int wordCount = 0;
if(splitData.length < index)
return;
for(int i = 0; i < splitData.length; i++){
if(!(splitData[i] == null) || !(splitData[i].length() == 0)) {
ArrayList<String> individualList = new ArrayList<String>();
individualList.add(splitData[i].trim());
if(wordCount == index)
results.add(splitData[i].trim());
wordCount++;
}
}
}
}
As you might notice I have not placed any limitations on number of rows or the number of columns. This is to cater to wider scenarios but if not, you might initialize with limits so memory allocation is optimized.
You can add each arraylist to another arraylist,
ArrayList allresults = new ArrayList();
result = ArrayListcsvToArray(csvData);
allresults.add(result);
public static ArrayListcsvToArray(String csvData){
ArrayList result = new ArrayList();
if (csvData != null){
String[] splitData = csvData.split(",");
for(int i = 0; i < splitData.length; i++){
if(!(splitData[i] == null) || !(splitData[i].length() == 0)) {
result.add(splitData[i].trim());
}
}
}
return result;
}

Merging values of 2 string arrays in one concatenated strings array

I have 2 string arrays.
string [] first = {"ajunkbc","ajunkHello","adedbc","abcjunk","add","ad","a","","junk","ajunk","aajunkbb"};
String [] second = {"abc","aHello","adedbc","abcjunk","add","ad","a","","junk","a","aajunkbb"};
I'd like the result of my merge() method to concatenate each element from the first array with the respective element of the second array separated by a comma.
Below is my code
private static String[] merge(String [] tests, String [] expectations){
List<String> testList = Arrays.asList(tests);
List<String> expectationsList = Arrays.asList(expectations);
List<String> retList = new ArrayList<String>();
for(String test : testList){
for(String val : expectationsList){
retList.add(test+","+val);
break;
}
}
This does not work. What's wrong with my code?
What's wrong is that you are looping over expectationsList and breaking out of the loop after the first iteration:
for(String val : expectationsList){
retList.add(test+","+val);
break; //<--- breaking out of loop after first iteration each time
}
So the result is that you are always retrieving the first element of expectationsList.
Since what you want is to loop over two arrays, you should use an index:
for (int i = 0; i < testList.size(); i++) {
retList.add(testList.get(i)+","+expectationsList.get(i));
}
Also, note that this implies that the size of testList is the same as the size of expectationsList. Your method should probably throw an exception if this is not the case.
Note that you do not need to convert the input arrays into lists. You can use them as-is.
private static String[] merge(String[] tests, String[] expectations) {
if (tests.length != expectations.length) {
throw new IllegalArgumentException("input not of same length");
}
String[] result = new String[tests.length];
for (int i = 0; i < tests.length; i++) {
result[i] = tests[i] + "," + expectations[i]);
}
return result;
}
Java 8 solution:
private static String[] merge(String[] tests, String[] expectations) {
if (tests.length != expectations.length) {
throw new IllegalArgumentException("input not of same length");
}
return IntStream.range(0, tests.length).mapToObj(i -> tests[i] + "," + expectations[i]).toArray(String[]::new);
}
You're iterating through each member of testList and then for each one, iterating through each member of expectationsList. You want to iterate through each of both of them together.
What you want to do is something like this:
private static String[] merge(String[] tests, String[] expectations) {
String[] result = new String[tests.length];
for(int i = 0; i < tests.length; i++) {
result[i] = tests[i] + "," + expectations[i];
}
return result;
}
This code makes the assumption that tests and expectations have the same length. You might want to do a check for that at the beginning:
if (tests.length != expectations.length) {
throw new IllegalArgumentException("tests and expectations are of different lengths")
}
Notice how now you're getting the element at the same index from both arrays.
Sidenote: You can iterate over arrays with the for each format. This works just fine:
String[] myStringArray = getStringArray();
for (String myString : myStringArray) {
// Do something
}
You don't need to convert to a List in order to iterate :)

How to shift each elements in array using loops?

I want to shift each elements in array to left if there is a null. E.g
public static void main(String[] args) {
String asd[] = new String[5];
asd[0] = "zero";
asd[1] = "one";
asd[2] = null;
asd[3] = "three";
asd[4] = "four;
I want the output to be
zero, one, three, four.
The length should also be adjusted
How can i do this using loops? I tried using if statements to check if an element is not null copy that value to another array. But i dont know how to copy if there is a null.
Given the kind of question, I suppose you want a simple, loop only and array only based solution, to understand how it works.
You have to iterate on the array, keeping an index of the new insertion point. At the end, using that same index, you can "shrink" the array (actually copy to a new smaller array).
String[] arr = {"a","b",null,"c",null,"d"};
// This will move all elements "up" when nulls are found
int p = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i] == null) continue;
arr[p] = arr[i];
p++;
}
// This will copy to a new smaller array
String[] newArr = new String[p];
System.arraycopy(arr,0,newArr,0,p);
Just tested this code.
EDIT :
Regarding the possibility of shrinking the array without using System.arraycopy, unfortunately in Java arrays size must be declared when they are instantiated, and can't be changed (nor made bigger nor smaller) after.
So if you have an array of length 6, and find 2 nulls, you have no way of shrinking it to a length of 4, if not creating a new empty array and then copying elements.
Lists can grow and shrink, and are more handy to use. For example, the same code with a list would be :
String[] arr = {"a","b",null,"c",null,"d"};
List<String> list = new ArrayList<>(Arrays.asList(arr));
Iterator<String> iter = list.iterator();
while (iter.hasNext()) if (iter.next() == null) iter.remove();
System.out.println(list);
Try:
int lengthNoNull = 0;
for(String a : asd) {
if(a != null) {
lengthNoNull++;
}
}
String[] newAsd = new String[lengthNoNull];
int i = 0;
for(String a : asd) {
if(a != null) {
newAsd[i++] = a;
}
}
Piece of code using only arrays.
String[] x = {"1","2","3",null,"4","5","6",null,"7","8","9"};
String[] a = new String[x.length];
int i = 0;
for(String s : x) {
if(s != null) a[i++] = s;
}
String[] arr = Arrays.copyOf(a, i);
Or this:
String[] xx = {"1","2","3",null,"4","5","6",null,"7","8","9"};
int pos = 0, i = 0;
String tmp;
for(String s : xx) {
if(s == null) {
tmp = xx[pos];
xx[pos] = s;
xx[i] = tmp;
pos++;
}
i++;
}
String[] arr = Arrays.copyOfRange(xx, pos, xx.length);

How to remove specific value from string array in java? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Removing an element from an Array (Java)
How to remove specific String array value for example
String[] str_array = {"item1","item2","item3"};
i want to remove "item2" from str_array pls help me i want output like
String[] str_array = {"item1","item3"};
I would do it as follows:
String[] str_array = {"item1","item2","item3"};
List<String> list = new ArrayList<String>(Arrays.asList(str_array));
list.remove("item2");
str_array = list.toArray(new String[0]);
If you must use arrays, System.arraycopy is the most efficient, scalable solution. However, if you must remove one element from an array several times, you should use an implementation of List rather than an array.
The following utilizes System.arraycopy in order to achieve the desired effect.
public static Object[] remove(Object[] array, Object element) {
if (array.length > 0) {
int index = -1;
for (int i = 0; i < array.length; i++) {
if (array[i].equals(element)) {
index = i;
break;
}
}
if (index >= 0) {
Object[] copy = (Object[]) Array.newInstance(array.getClass()
.getComponentType(), array.length - 1);
if (copy.length > 0) {
System.arraycopy(array, 0, copy, 0, index);
System.arraycopy(array, index + 1, copy, index, copy.length - index);
}
return copy;
}
}
return array;
}
Also, you can increase the method's efficiency if you know that your array consists of only Comparable objects. You can use Arrays.sort to sort them before passing them through the remove method, modified to use Arrays.binarySearch to find index rather than a for loop, raising that portion of the method's efficiency from O(n) to O(nlogn).
Other Option is to copy array to other array accept than remove item.
public static String[] removeItemFromArray(String[] input, String item) {
if (input == null) {
return null;
} else if (input.length <= 0) {
return input;
} else {
String[] output = new String[input.length - 1];
int count = 0;
for (String i : input) {
if (!i.equals(item)) {
output[count++] = i;
}
}
return output;
}
}

Remove Null Value from String array in java

How to remove null value from String array in java?
String[] firstArray = {"test1","","test2","test4",""};
I need the "firstArray" without null ( empty) values like this
String[] firstArray = {"test1","test2","test4"};
If you want to avoid fencepost errors and avoid moving and deleting items in an array, here is a somewhat verbose solution that uses List:
import java.util.ArrayList;
import java.util.List;
public class RemoveNullValue {
public static void main( String args[] ) {
String[] firstArray = {"test1", "", "test2", "test4", "", null};
List<String> list = new ArrayList<String>();
for(String s : firstArray) {
if(s != null && s.length() > 0) {
list.add(s);
}
}
firstArray = list.toArray(new String[list.size()]);
}
}
Added null to show the difference between an empty String instance ("") and null.
Since this answer is around 4.5 years old, I'm adding a Java 8 example:
import java.util.Arrays;
import java.util.stream.Collectors;
public class RemoveNullValue {
public static void main( String args[] ) {
String[] firstArray = {"test1", "", "test2", "test4", "", null};
firstArray = Arrays.stream(firstArray)
.filter(s -> (s != null && s.length() > 0))
.toArray(String[]::new);
}
}
It seems no one has mentioned about using nonNull method which also can be used with streams in Java 8 to remove null (but not empty) as:
String[] origArray = {"Apple", "", "Cat", "Dog", "", null};
String[] cleanedArray = Arrays.stream(firstArray).filter(Objects::nonNull).toArray(String[]::new);
System.out.println(Arrays.toString(origArray));
System.out.println(Arrays.toString(cleanedArray));
And the output is:
[Apple, , Cat, Dog, , null]
[Apple, , Cat, Dog, ]
If we want to incorporate empty also then we can define a utility method (in class Utils(say)):
public static boolean isEmpty(String string) {
return (string != null && string.isEmpty());
}
And then use it to filter the items as:
Arrays.stream(firstArray).filter(Utils::isEmpty).toArray(String[]::new);
I believe Apache common also provides a utility method StringUtils.isNotEmpty which can also be used.
If you actually want to add/remove items from an array, may I suggest a List instead?
String[] firstArray = {"test1","","test2","test4",""};
ArrayList<String> list = new ArrayList<String>();
for (String s : firstArray)
if (!s.equals(""))
list.add(s);
Then, if you really need to put that back into an array:
firstArray = list.toArray(new String[list.size()]);
Using Google's guava library
String[] firstArray = {"test1","","test2","test4","",null};
Iterable<String> st=Iterables.filter(Arrays.asList(firstArray),new Predicate<String>() {
#Override
public boolean apply(String arg0) {
if(arg0==null) //avoid null strings
return false;
if(arg0.length()==0) //avoid empty strings
return false;
return true; // else true
}
});
This is the code that I use to remove null values from an array which does not use array lists.
String[] array = {"abc", "def", null, "g", null}; // Your array
String[] refinedArray = new String[array.length]; // A temporary placeholder array
int count = -1;
for(String s : array) {
if(s != null) { // Skips over null values. Add "|| "".equals(s)" if you want to exclude empty strings
refinedArray[++count] = s; // Increments count and sets a value in the refined array
}
}
// Returns an array with the same data but refits it to a new length
array = Arrays.copyOf(refinedArray, count + 1);
Quite similar approve as already posted above. However it's easier to read.
/**
* Remove all empty spaces from array a string array
* #param arr array
* #return array without ""
*/
public static String[] removeAllEmpty(String[] arr) {
if (arr == null)
return arr;
String[] result = new String[arr.length];
int amountOfValidStrings = 0;
for (int i = 0; i < arr.length; i++) {
if (!arr[i].equals(""))
result[amountOfValidStrings++] = arr[i];
}
result = Arrays.copyOf(result, amountOfValidStrings);
return result;
}
A gc-friendly piece of code:
public static<X> X[] arrayOfNotNull(X[] array) {
for (int p=0, N=array.length; p<N; ++p) {
if (array[p] == null) {
int m=p; for (int i=p+1; i<N; ++i) if (array[i]!=null) ++m;
X[] res = Arrays.copyOf(array, m);
for (int i=p+1; i<N; ++i) if (array[i]!=null) res[p++] = array[i];
return res;
}
}
return array;
}
It returns the original array if it contains no nulls. It does not modify the original array.
Those are zero-length strings, not null. But if you want to remove them:
firstArray[0] refers to the first element
firstArray[1] refers to the second element
You can move the second into the first thusly:
firstArray[0] = firstArray[1]
If you were to do this for elements [1,2], then [2,3], etc. you would eventually shift the entire contents of the array to the left, eliminating element 0. Can you see how that would apply?

Categories