TreeNode[] children = grid[row][col].getChildren();
I would like a simple function that can tell me how many objects are in this array? getChildren() will return an object of size no larger than 4, for example:
children[0] = null;
children[1] = TreeNode Object
children[2] = null;
children[3] = null;
Why don't you write it yourself:
public static <T> int getLength(T[] arr){
int count = 0;
for(T el : arr)
if (el != null)
++count;
return count;
}
Code:
Arrays.stream(list).filter(e -> e != null).count();
This should work. Essentially the same with the function written for you and not TreeNode specific.
int initLength(Object[] myArray) {
int count = 0;
for (Object obj : myArray) {
if ( obj != null ) count++;
}
return count;
}
I called it initLength because those items are init'd but call it what you like. Some would say it's init'd when you define it, regardless of whether the contents are null.
Other alternative:
ArrayList l = new ArrayList(Arrays.asList(children));
l.removeAll(Collections.singleton(null));
l.size();
Perhaps overkill to use predicates, but here's a Guava solution:
int numNotNull = Iterables.size( Iterables.filter( Arrays.asList( children ),
Predicates.notNull() ));
In Java 8, you can use Math.toIntExact and Arrays.stream to construct a nice one-liner:
Math.toIntExact(Arrays.stream(row).filter(s -> s != null).count())
Related
I wanted to find an intersection between two arraylist that are of byte[] format and return the common indices. I have the code as follows and it works correctly:
ArrayList<Integer> intersect = new ArrayList<Integer>();
for(int j = 0; j < A.size(); j++)
{
byte [] t = A.get(j);
for (int j1 = 0; j1 < B.size(); j1++)
{
byte[] t1 = B.get(j1);
if (Arrays.equals(t, t1))
{
intersect.add(j);
break;
}
}
}
However, as you can see, I have to use two for loops. Is there any way I can do it without using any for loops? I have tried to use "retainAll" but for some reason, it kept giving me an empty array. What can be the possible reason for that?
If you just dont want to use for loops, you may try the Java 8 streams, since you have not shared the complete code I did not try it out.
List<T> intersect = list1.stream()
.filter(list2::contains)
.collect(Collectors.toList());
I think for T your solution with brutforce is not so bad. This is a small refactoring of it. Yes, for specific T (e.g. int) you could use special structures, but in general case, I think this is not implementable.
public static <T> List<Integer> intersect(List<T> A, List<T> B, BiPredicate<T, T> isEqual) {
List<Integer> intersect = new LinkedList<>();
int i = -1;
for (T a : A) {
i++;
if (B.stream().anyMatch(b -> isEqual.test(a, b)))
intersect.add(i);
}
return intersect;
}
Client code could look like:
List<byte[]> a = Collections.emptyList();
List<byte[]> b = Collections.emptyList();
List<Integer> intersect = intersect(a, b, Arrays::equals);
This may help:
public <T> List<T> intersection(List<T> list1, List<T> list2) {
List<T> list = new ArrayList<T>();
for (T t : list1) {
if(list2.contains(t)) {
list.add(t);
}
}
return list;
}
Reference:
Intersection and union of ArrayLists in Java
I'm trying to write a Java function which takes a List of Lists holding objects of any class, and then calculates the size of the set consisting of all different combinations of inner list objects, where all objects come from different lists. The algorithm is simple:
int combos(List<List<Object>> inList) {
int res = 1;
for(List<Object> list : inList) {
res *= list.size();
}
return res;
}
But I'm getting this error when trying to run the function with a List<List<Integer>> object as input parameter:
List<List<Integer>> input = new ArrayList<List<Integer>>();
input.add(new ArrayList<Integer>());
input.get(0).add(1);
input.get(0).add(2);
combos(input);
The error:
The method combos(List<List<Object>>) in the type SpellChecker is not applicable for the arguments (List<List<Integer>>)
As far as I understand, Object is the parent class of Integer. So why doesn't this work? How can I make it work?
The relationship between Object and Integer does not apply to List<Object> and List<Integer>, see e.g. this related question for more details.
Use a type parameter:
<T> int combos(List<List<T>> inList) {
int res = 1;
for(List<T> list : inList) {
res *= list.size();
}
return res;
}
One solution is to use a type parameter in combos:
<T> int combos(List<List<T>> inList) {
int res = 1;
for(List<T> list : inList) {
res *= list.size();
}
return res;
}
This is closely related to this question about nested generics. The answer in that question provides some good info.
On top of the two good answers you already got here is another option.
public static void main(String[] args) {
List<List<Integer>> input = new ArrayList<>();
input.add(new ArrayList<>());
input.get(0).add(1);
input.get(0).add(2);
combos(input);
}
static int combos(List<? extends List<?>> inList) {
int res = 1;
for (List<?> list : inList) {
res *= list.size();
}
return res;
}
This also works, if you don't need to specialize the List Datatype as List<Integer>
List<List<Object>> input = new ArrayList<List<Object>>();
input.add( new ArrayList<Object>() );
input.get( 0 ).add( new Integer(1) );
input.get( 0 ).add( new Integer(2) );
combos( input );
I have an Iterator - placed somewhere in the middle of my collection.
I want to loop over the collection from there on, returning a special element if I find it.
If I reach !hasNext() then I want to start at the begining, but I want to stop if I reach the place where I started first.
The best Idea how to solve that seems currently to save the "first" (wherever the iterator pointed when I started) element and then stop if I find that one again.
And that works as long as items can occure only once in my collection (i.e. in a HasSet).
Any better ideas how to do such thing? Iterator doesn't seem to supply a pointer/number back to me that I could compare.
With Guava Iterators (Java 7):
Iterator<YourType> iterator = Iterators.concat(yourIteratorPlaceSomewhereInMiddle, Iterators.limit(yourCollection.iterator(), positionOfSomewhereInMiddle));
With Streams (Java 8):
Optional<YourType> theAnswer = IntStream.iterate(positionOfSomewhereInMiddle, pos -> ++pos)
.map(pos -> pos % sizeOfCollection)
.mapToObj(yourCollection::get)
.limit(sizeOfCollection)
.filter(element -> element is 42)
.findFirst();
If the collection is a list, then it can be done with below code
private void Object traverseList(List namesList, int startIndex ) {
int index = 0;
Iterator iterator = namesList.listIterator(startIndex);
while (iterator.hasNext() && index < namesList.size()){
Object element = iterator.next();
/*if(element.isSpecialElement()){
return element;
}
*/
index++;
System.out.println(element);
if(!iterator.hasNext()){
iterator = namesList.iterator();
}
}
}
Since you want to transverse all the elements in the list, I am making use of list size. And during iteration, if the special element is found, it can be returned.
To start to iterate a Set from a definedValue I do :
public void iterate(Set<Sample> set, Sample definedValue){
Iterator<Sample> iterator = set.iterator();
while(iterator.hasNext()){
Sample currentSample = iterator.next();
if(currentSample.equals(definedValue)){
while(iterator.hasNext()){
Sample sampleToConsider = iterator.next();
//Then do anything
}
}
}
}
The solution becomes more simple if you:
Don't use Iterator, it makes it more complicated
Use a List instead of Set as Set is ill-suited for this use case
public static void main(String[] args) {
Set<String> yourStartingCollection = new HashSet<>();
List<String> fooList = new ArrayList<>(yourStartingCollection);
Optional<String> specialElement = findSpecialElementStartingFromMiddle(fooList);
if (specialElement.isPresent()) {
// found it!
}
}
private static Optional<String> findSpecialElementStartingFromMiddle(List<String> elements) {
int middleIndex = elements.size() / 2;
Optional<String> result = Optional.empty();
for (int i = middleIndex; i < elements.size(); i++) {
String element = elements.get(i);
if (isSpecial(element)) {
result = Optional.of(element);
break;
}
}
if (result.isPresent()) {
return result;
}
for (int i = 0; i < middleIndex; i++) {
String element = elements.get(i);
if (isSpecial(element)) {
result = Optional.of(element);
break;
}
}
return result;
}
private static boolean isSpecial(String element) {
return element.equals("I'm special");
}
I want a function / data structure that can do this:
func(int dim){
if(dim == 1)
int[] array;
else if (dim == 2)
int[][] array;
else if (dim == 3)
int[][][] array;
..
..
.
}
anyone know how?
Edit
Or you could use Array.newInstance(int.class, sizes). Where sizes is an int[] containing the desired sizes. It will work better because you could actually cast the result to an int[][][]...
Original Answer
You could use the fact that both int[] and Object[] are Objects. Given that you want a rectangular multidimensional array with sizes given by the list sizes
Object createIntArray(List<Integer> sizes) {
if(sizes.size() == 1) {
return new int[sizes.get(0)];
} else {
Object[] objArray = new Object[sizes.get(0)];
for(int i = 0; i < objArray.length; i++) {
objArray[i] = createIntArray(sizes.subList(1, sizes.size());
}
return objArray;
}
}
You lose all static type checking, but that will happen whenever you want a dynamically dimensioned array.
If your purpose is to create a truly dynamic array, then you should look at the Array object in the JDK. You can use that to dynamically generate an array of any dimension. Here is an example:
public void func(int dim) {
Object array = Array.newInstance(int.class, new int[dim]);
// do something with the array
}
Once the array Object has been created, you can use the methods of the java.lang.reflect.Array class to access, add, remove elements from the multi-dimension array that was created. In also includes utility methods to determine the length of the array instance.
You can even check the dimension of the array using:
public int getDimension(Object array) {
int dimension = 0;
Class cls = array.getClass();
while (cls.isArray()) {
dimension++;
cls = cls.getComponentType();
}
return dimension;
}
People have post good solutions already, but I thought it'd be cool (and good practice) if you wrap the dynamic multidimensional array into a class, which can use any data structure to represent the multi-dimensional array. I use hash table so you have virtually unlimited size dimensions.
public class MultiDimArray{
private int myDim;
private HashMap myArray;
public MultiDimArray(int dim){
//do param error checking
myDim = dim;
myArray= new HashMap();
}
public Object get(Integer... indexes){
if (indexes.length != myDim){throw new InvalidArgumentException();}
Object obj = myArray;
for (int i = 0; i < myDim; i++){
if(obj == null)
return null;
HashMap asMap = (HashMap)obj;
obj = asMap.get(indexes[i]);
}
return obj;
}
public void set(Object value, Integer... indexes){
if (indexes.length != myDim){throw new InvalidArgumentException();}
HashMap cur = myArray;
for (int i = 0; i < myDim - 1; i++){
HashMap temp = (HashMap)cur.get(indexes[i]);
if (temp == null){
HashMap newDim = new HashMap();
cur.put(indexes[i], newDim);
cur = newDim;
}else{
cur = temp;
}
}
cur.put(indexes[myDim -1], value);
}
}
and you can use the class like this:
Object myObj = new Object();
MultiDimArray array = new MultiDimArray(3);
array.put(myObj, 0, 1, 2);
array.get(0, 1, 2); //returns myObj
array.get(4, 5, 6); //returns null
What about a class like following?
class DynaArray {
private List<List> repository = new ArrayList<List>();
public DynaArray (int dim) {
for (int i = 0; i < dim; i++) {
repository.add(new ArrayList());
}
}
public List get(int i) {
return repository.get(i);
}
public void resize(int i) {
// resizing array code
}
}
In Java I want to convert a nested List which contains at the deepest level a uniform type into an multidimensional array of that type. For example, ArrayList<ArrayList<ArrayList<ArrayList<String>>>> into String[][][][]. I've tried several things and I only can obtain an array of objects like Object[][][][]. For 'simple lists' it seems that Apache Commons Lang does the work but I cannot figure out for nested cases.
Update:
In order to obtain a multidimensional array of Object type I'm using a recursive function so I cannot set the key type using toArray() see excerpt:
// the argument of this function is a (nested) list
public static Object convert(Object object) {
Object[] result = null;
List list = (List) object;
if (list != null) {
Object type = getElementType(list);
if (type instanceof List) {
int size = list.size();
result = new Object[size];
for (int counter = 0; counter < size; counter++) {
Object element = list.get(counter);
result[counter] = (element != null) ? convert(element) : null;
}
} else {
result = list.toArray();
}
}
return result;
}
private static Object getElementType(List list) {
Object result = null;
for (Object element : list) {
if (element != null) {
result = element;
break;
}
}
return result;
}
To create any kind of non-Object array, you need to pass a type key to the toArray method. This is because for generic types (e.g., ArrayList), the type argument is erased (so, at runtime, ArrayList<String> is treated as a plain ArrayList), whereas for arrays, the type is not.
It seems you already have the Object array creation sorted, so with that and the use of the type key, I think you're all sorted! :-)
This is the way that someone suggested to solved for String type. Cast2(List<?>) returns the multidimensional array. It may be generalized to use the class type as parameter. Thank you for your comments.
static int dimension2(Object object) {
int result = 0;
if (object instanceof List<?>) {
result++;
List<?> list = (List<?>) object;
for (Object element : list) {
if (element != null) {
result += dimension2(element);
break;
}
}
}
return result;
}
static Object cast2(List<?> l) {
int dim = dimension2(l);
if (dim == 1) {
return l.toArray(new String[0]);
}
int[] dims = new int[dimension2(l)];
dims[0] = l.size();
Object a = Array.newInstance(String.class, dims);
for (int i = 0; i < l.size(); i++) {
List<?> e = (List<?>) l.get(i);
if (e == null) {
Array.set(a, i, null);
} else if (dimension2(e) > 1) {
Array.set(a, i, cast2(e));
} else {
Array.set(a, i, e.toArray(new String[0]));
}
}
return a;
}
hehe, heres a answer too but i dunno if that really helps:
List<ArrayList<ArrayList<ArrayList<String>>>> x = new ArrayList<ArrayList<ArrayList<ArrayList<String>>>>();
public static void main(String[] args) throws MalformedURLException, IOException, SecurityException, NoSuchFieldException {
Type t = ((ParameterizedType)(jdomTEst.class.getDeclaredField("x").getGenericType())).getActualTypeArguments()[0];
int[] dims = new int[t.toString().split("List").length];
Object finalArray = Array.newInstance(String.class, dims);
System.out.println(finalArray);
}
this prints: [[[[Ljava.lang.String;#4e82701e
looks pretty messy but i love reflections :)
You can use transmorph :
ArrayList<ArrayList<ArrayList<ArrayList<String>>>> arrayList = new ArrayList<ArrayList<ArrayList<ArrayList<String>>>>();
/// populate the list ...
[...]
Transmorph transmorph = new Transmorph(new DefaultConverters());
String[][][][] array = transmorph.convert(arrayList, String[][][][].class);