I should write a method that returns all cousins of the Person as an array of Person objects. A Person object has mother, father, children[] etc. as its instance variables and I should use this method to find all siblings of a Person's uncles and aunts then their children.
public Person[] allSiblings(){
int a = this.mother.children.length - 1;
Person[] siblings = new Person[a];
for(i=0; i<siblings.length; i++){
if(this.mother.children[i] == this)
continue;
else{
siblings[i] = this.mother.children[i];
}
}
return siblings;
}
So how can I merge these children arrays and return as one Person array in allCousins() method. I know it would be easier to use ArrayList but we are not allowed.
Thanks in advance.
Have a look at
How can I concatenate two arrays in Java?
There are some methods on how to do that. The trick is to either use a ready made function (which you probably are not allowed if Lists are forbidden) or to create a new Array with the sum of the two original Arrays as length.
The link mentioned by JoshOvi is good one. If you want to create your own implementation, consider ArrayUtils as reference -
public Object[] mergeArray(final Object[] arr1, final Object[] arr2) {
if (arr1 == null) {
return clone(arr2);
}
else if (arr2 == null) {
return clone(arr1);
}
Object[] mergedArray = new Object[arr1.length+arr2.length];
System.arraycopy(arr1, 0, mergedArray, 0, arr1.length);
System.arraycopy(arr2, 0, mergedArray, arr1.length, arr2.length);
return mergedArray;
}
public Object[] clone(Object[] array) {
if (array == null) {
return null;
}
return (Object[]) array.clone();
}
Related
The goal here is to insert elements into a TreeSet where the ordering is done by a custom objects internal List.
public class CustomObject implements Comparable<CustomObject> {
List<Integer> innerObjectList = new ArrayList<>();
#Override
public boolean compareTo(CustomObject o) {
#compare natural ordering of elements in array.
}
}
This is what I'm currently doing, it works but I was hoping to find a native way to do it.
#Override
public int compareTo(#NotNull AisleMap o) {
if (o.aisles.size() > aisles.size())
return 1;
if (o.aisles.size() < aisles.size())
return -1;
for (int i = 0; i<aisles.size(); i++) {
int compare = o.aisles.get(i).compareTo(aisles.get(i));
if( compare != 0) {
return compare;
}
}
return 0;
}
I'm trying to figure out how to do something like o.innerObjectList.compare(toInnerObjectList); However I'm not entirely sure how to do this so that the TreeSet orders the objects by the array properly. Is there an easy way to compare the "natural" order of elements in an array to each other? Only way I thought of was to check for size then if equal check contents until one index of one array is larger than the same index of another.
ex: the ordering would be like so {1,2,5} -> {1,2,4} -> {1,2,3}
This is a homework lab for school. I am trying to reverse a LinkedList, and check if it is a palindrome (the same backwards and forwards). I saw similar questions online, but not many that help me with this. I have made programs that check for palindromes before, but none that check an array or list. So, first, here is my isPalindrome method:
public static <E> boolean isPalindrome(Collection<E> c) {
Collection<E> tmp = c;
System.out.println(tmp);
Collections.reverse((List<E>) c);
System.out.println(c);
if(tmp == c) { return true; } else { return false; }
}
My professor wants us to set the method up to accept all collections which is why I used Collection and cast it as a list for the reverse method, but I'm not sure if that is done correctly. I know that it does reverse the list. Here is my main method:
public static void main(String...strings) {
Integer[] arr2 = {1,3,1,1,2};
LinkedList<Integer> ll2 = new LinkedList<Integer>(Arrays.asList(arr2));
if(isPalindrome(ll2)) { System.out.println("Successful!"); }
}
The problem is, I am testing this with an array that is not a palindrome, meaning it is not the same backwards as it is forwards. I already tested it using the array {1,3,1} and it works fine because that is a palindrome. Using {1,3,1,1,2} still returns true for palindrome, though it is clearly not. Here is my output using the {1,3,1,1,2} array:
[1, 3, 1, 1, 2]
[2, 1, 1, 3, 1]
Successful!
So, it seems to be properly reversing the List, but when it compares them, it assumes they are equal? I believe there is an issue with the tmp == c and how it checks whether they are equal. I assume it just checks if it contains the same elements, but I'm not sure. I also tried tmp.equals(c), but it returned the same results. I'm just curious is there is another method that I can use or do I have to write a method to compare tmp and c?
Thank you in advance!
Tommy
In your code c and tmp are links to same collection and tmp == c will be always true. Your must clone your collection to new instance, for example: List<E> tmp = new ArrayList(c);.
Many small points
public static <E> boolean isPalindrome(Collection<E> c) {
List<E> list = new ArrayList<>(c);
System.out.println(list);
Collections.reverse(list);
System.out.println(list);
return list.equals(new ArrayList<E>(c));
}
Reverse only works on an ordered list.
One makes a copy of the collection.
One uses equals to compare collections.
public static void main(String...strings) {
int[] arr2 = {1, 3, 1, 1, 2};
//List<Integer> ll2 = new LinkedList<>(Arrays.asList(arr2));
List<Integer> ll2 = Arrays.asList(arr2);
if (isPalindrome(ll2)) { System.out.println("Successful!"); }
}
You need to copy the Collection to a List / array. This has to be done, since the only ordering defined for a Collection is the one of the iterator.
Object[] asArray = c.toArray();
You can apply the algorithm of your choice for checking if this array is a palindrom to check, if the Collection is a palindrom.
Alternatively using LinkedList it would be more efficient to check, if the list is a palindrom without creating a new List to reverse:
public static <E> boolean isPalindrome(Collection<E> c) {
List<E> list = new LinkedList<>(c);
Iterator<E> startIterator = list.iterator();
ListIterator<E> endIterator = list.listIterator(list.size());
for (int i = list.size() / 2; i > 0; i--) {
if (!Objects.equals(startIterator.next(), endIterator.previous())) {
return false;
}
}
return true;
}
Hi I made up this class to add to string arrays and remove elements from them. I also did one that prepares a group of values for writing to a csv file. However I would like to do it so that it will take in any value (for the first two methods as the last one will always be a string) How do I make it Generic so?
And ps I know I shouldnt send the two dimension arguments for the csv builder but I only found out how to get the row dimension now.:)
public class ManipulateList {
public static String [] removeFromArray(String []old_array,int index) {
String []old_vals = old_array;
int old_length= old_vals.length;
int new_length= old_length-1;
String[] new_vals = new String[new_length];
System.arraycopy(old_vals, 0, new_vals, 0, index);
if(index+1!=old_length) {
System.arraycopy(old_vals, index+1, new_vals,index,old_length-1-index);
}
return new_vals;
}
public static String[] addToArray(String []old_array,String element) {
String new_element=element;
String[] old_vals = old_array;
int old_length= old_vals.length;
int new_length= old_length+1;
String[] new_vals = new String[new_length];
System.arraycopy(old_vals, 0, new_vals, 0, old_length);
new_vals[old_length]=new_element;
return new_vals;
}
public static String[] createCsvList(String[][] lists, int contents1,int contents2){
String[][] csvarray=new String[contents1][contents2];
csvarray = lists;
String[]newcsv=new String[contents2];
StringBuilder newline = new StringBuilder();
for (int i = 0; i<contents2;i++) {
for (int j = 0; j<contents1;j++) {
newline.append(csvarray[j][i]);
if(contents1-j>1) {
newline.append(",");
}
}
newcsv[i]=newline.toString();
newline= new StringBuilder();
}
return newcsv;
}
}
Pretty much, replace String[] with T[] and you're done.
Here's the first one. You'll notice that I mostly just replaced String[] with T[] and added <T> to the method signature.
public static <T> T[] removeFromArray(T[] old_array,int index)
{
T[] old_vals = old_array;
int old_length = old_vals.Length;
int new_length = old_length - 1;
#SuppressWarnings("unchecked") T[] new_vals = (T[]) Array.newInstance(old_array.getClass().getComponentType(), new_length);
System.arraycopy(old_vals, 0, new_vals, 0, index);
if(index + 1 != old_length)
{
System.arraycopy(old_vals, index+1, new_vals, index,old_length - 1 - index);
}
return new_vals;
}
Edit:
Apparently, to create a new array, it has to be done like this:
public T[] createArray(Class<T> cls, int size) throws Exception
{
#SuppressWarnings("unchecked") T[] array = (T[])Array.newInstance(cls, size);
return array;
}
It would be better to use a List, or better yet, an object containing a List, instead of a String[]. Then you would not have to write your own methods to add elements to arrays.
If you really want to use arrays for some reason, it's fairly difficult, since the following is illegal:
T[] myNewList = new T[];
The compiler does not have the information at runtime to know what T is when you're calling the method (due to type erasure). You can fake it in various ways such as using ArrayList.toArray(), but I'd just avoid the problem entirely and use Lists, as mentioned above.
However, for CSV, I'm not sure why you would want anything except for Strings anyway. CSV files are effectively lists of lists of strings.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to create ArrayList (ArrayList<T>) from array (T[]) in Java
How to implement this method:
List<Integer> toList(int[] integers) {
???
//return Arrays.asList(integers); doesn't work
}
There's probably a built-in method to do it somewhere* (as you note, Arrays.asList won't work as it expects an Integer[] rather than an int[]).
I don't know the Java libraries well enough to tell you where that is. But writing your own is quite simple:
public static List<Integer> createList(int[] array) {
List<Integer> list = new ArrayList<Integer>(array.length);
for (int i = 0; i < array.length; ++i) {
list.add(array[i]);
}
return list;
}
Obviously one downside of this is that you can't do it generically. You'll have to write a separate createList method for each autoboxed primitive type you want.
*And if there isn't, I really wonder why not.
Use commons-lang3 org.apache.commons.lang3.ArrayUtils.toObject(<yout int array>) and then java.util.Arrays.asList(<>)
ArrayUtils.toObject() will copy the array, and Array.asList() will simply create list that is backed by new array.
int[] a = {1, 2, 3};
List<Integer> aI = Arrays.asList(ArrayUtils.toObject(a));
EDIT: This wont work if you want to add() new elements (resize) though the list interface, if you want to be able to add new elements, you can use new ArrayList(), but this will create one more copy.
List<Integer> asList(final int[] integers) {
return new AbstractList<Integer>() {
public Integer get(int index) {
return integers[index];
}
public int size() {
return integers.length;
}
};
}
List<Integer> toList(int[] integers) {
// Initialize result's size to length of the incoming array
// this way it will not require reallocations
ArrayList<Integer> result = new ArrayList<Integer>( integers.length );
for ( int cur: integers )
{
result.add( Integer.valueOf( cur ) );
}
return result;
}
I do not think there is a quick way to do it unfortunately. I believe you will have to iterate the array and add it one by one.
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
public class Listing {
public static void main(String[] args) {
int[] integers = {1,2,3,4};
java.util.List<Integer> list = new ArrayList<Integer>();
for (int i=0; i< integers.length; i++)
{
list.add(integers[i]);
}
System.out.println(list);
}
}
Tested and working as expected!
I still have a question about Enumerations. Here's a quick sketch of the situation.
I have a class Backpack that has a Hashmap content with as keys a variable of type long, and as value an ArrayList with Items.
I have to write an Enumeration that iterates over the content of a Backpack. But here's the catch: in a Backpack, there can also be another Backpack. And the Enumeration should also be able to iterate over the content of a backpack that is in the backpack. (I hope you can follow, I'm not really good at explaining..)
Here is the code I have:
public Enumeration<Object> getEnumeration() {
return new Enumeration<Object>() {
private int itemsDone = 0;
//I make a new array with all the values of the HashMap, so I can use
//them in nextElement()
Collection<Long> keysCollection = getContent().keySet();
Long [] keys = keysCollection.toArray(new Long[keysCollection.size()]);
public boolean hasMoreElements() {
if(itemsDone < getContent().size()) {
return true;
}else {
return false;
}
}
public Object nextElement() {
ArrayList<Item> temporaryList= getContent().get(keys[itemsDone]);
for(int i = 0; i < temporaryList.size(); i++) {
if(temporaryList.get(i) instanceof Backpack) {
return temporaryList.get(i).getEnumeration();
}else {
return getContent().get(keys[itemsDone++]);
}
}
}
};
Will this code work decently? It's just the "return temporaryList.get(i).getEnumeration();" I'm worried about. Will the users still be able to use just the hasMoreElemens() and nextElement() like he would normally do?
Any help is appreciated,
Harm De Weirdt
You need to create a Stack<Enumeration<Object>>. When you see another Backpack, you push a new Enumeration on that element into the Stack. You always nextElement() from the top of the stack. If the top element is empty, you pop it off. Repeat until the Stack.isEmpty().
Another perhaps simpler technique (depending on how comfortable you are with recursion) is to use "inner" enumerations, which itself can have inner enumerations. Here's a code sample using Iterator on Object[]. It recursively iterates into any nested Object[].
public class RecursiveIterator implements Iterator<Object> {
final Object[] arr;
int index = 0;
Iterator<Object> inner;
RecursiveIterator(Object[] arr) {
this.arr = arr;
}
#Override public boolean hasNext() {
while (true) {
if (inner != null) {
if (inner.hasNext()) {
return true;
} else {
inner = null;
index++;
}
}
if (index == arr.length) return false;
if (arr[index] instanceof Object[]) {
inner = new RecursiveIterator((Object[]) arr[index]);
} else {
return true;
}
}
}
#Override public Object next() {
if (!hasNext()) throw new NoSuchElementException();
return (inner != null) ? inner.next() : arr[index++];
}
#Override public void remove() {
throw new UnsupportedOperationException();
}
}
Here's a test harness:
static void dump(Object[] arr) {
Iterator<Object> iter = new RecursiveIterator(arr);
while (iter.hasNext()) {
System.out.print(iter.next() + " ");
}
System.out.println("(done)");
}
public static void main(String[] args) throws FileNotFoundException {
dump(new Object[] {
1,
2,
new Object[] {
3,
new Object[] { 4 },
5,
},
6,
new Object[] {},
7,
});
dump(new Object[] {
new Object[] {},
new Object[] {
new Object[] {
new Object[] {},
},
},
new Object[] {},
new Object[] { null },
});
}
This prints:
1 2 3 4 5 6 7 (done)
null (done)
If it was for practical purposes and not homework, I would use the Iterator interface instead of the old Enumeration. For iterators you have some nice utilities in the apache collections project.
Secondly, your solution seems to have a bug. The method nextElement() should return the elements themselves, but the line return temporaryList.get(i).getEnumeration() returns an Enumeration object instead.
--EDIT--
polygenelubricants suggested a nice, elegant solution. I thought of something else. You can implement a generic ChainEnumeration class (implements Enumeration), that receives a list of Enumerations and allows enumerating the underlying items. In your tree structure, return a simple enumeration with one item for leafs, and a chain enumeration of inner nodes.
The implementation of ChainEnumeration is simple: it manages a list of iterators, plus a reference to the current active iterator, where items are taken from.