Creating Arrays of Objects With Methods - java

I couldn't really come up with the words as to how to describe my question in the title.
What I'm trying to accomplish is something like this: (Pseudo code)
SuperClass[] superArray = new SuperClass[];
// work on superArray
// ...
SubClass[] subArray = superArray.asAnArrayOfSubClass();
`
Is something like this possible?

You cannot add members : methods or fields to an array. So no, it is not possible :
SubClass[] subArray = superArray.asAnArrayOfSubClass();
To define a behavior for an array, instead create a method where you pass the array :
SubClass[] doThat(SuperClass[] superArray){
....
}
Even if conceptually, a type should not know its subtypes, if it is your requirement it is valid to convert manually an array of a specific type to an array of a subclass of this specific type.
For example, you can have employees stored in an array that at time are promoted as managers. This method could do this conversion :
Manager[] promote(Employee[] employees){
Manager[] managers = new Manager[employees.length];
for (int i=0; i<employees.length; i++){
Employee e = employee[i];
managers[i] = new Manager(....);
}
return managers;
}

No. Not possible. Because not every Parent is a Child. The reverse is possible as Every child is a Parent.
See the below example.
Object[] supers = new Object[5];
Integer[] childs = supers // Errrr.. No I have Strings, Doubles too
But the reverse is possible
Integer[] childs = new Integer[5];
Object[] supers = childs // Ok, I can hold any object.

Casting to subclasses is a code smell, and probably you should reconsider your design. Also try to use a java collection api (Iterable, Collection, List), with generics, and not primitive arrays, which you can subclass adding your own methods like the example below:
public interface IteratorWithIndex<T> extends Iterator<T> {
int index();
}

There are restrictions that your subclass should match super class wrt properties and methods and you are only overriding those.
Below is an example of how you could do this using streams API.
Number[] array = new Number[]{12, 20, 30, 40};
List<Integer> list = Arrays.stream(array)
.map(e -> (Integer) e)
.collect(Collectors.toList());
System.out.println(list.toArray());

Related

What is the best way to convert a raw vector to type safe list(Arraylist)

I have a function that return a raw vector. I know that all the elements in the vector are string but the code stays for leagacy reasons. I want to get a arraylist from this data.
One naive way is to iterate the vector and add elements to the list. Is there any short way of doing it which can prevent looping. Or may be a direct function which enables this.
Edit:
Example:
Vector f1() {} //f1 returns raw vector
I want to achieve the following:
List<String> l = new ArrayList<String>();
Vector vec = f1();
for(Object obj: vec) {
l.add((String) obj);
}
Note: I have not checked if the above code compiles. Please treat it as a pseudo code
If you are 100% sure the Vector only contains Strings, the simplest way is:
List<String> list = new ArrayList<>(vector);
Note that this will compile and run fine, even if you Vector contains other types of objects. However this:
list.get(i);
will throw a ClassCastException if the i-th element was not a String.
Since you have a raw Vector you will get warnings. If you want to get rid of them you can use:
#SuppressWarnings(value = {"unchecked", "rawtypes"})
public static List<String> rawVectorToList(Vector v) {
return new ArrayList<>(v);
}
An alternative to detect casting issues fast is to copy the array manually (what the copy constructor does under the hood):
Vector v = ...;
String[] elements = Arrays.copyOf(v.toArray(), v.size(), String[].class);
List<String> list = Arrays.asList(elements);
or if you need the list to be mutable:
List<String> list = new ArrayList<> (Arrays.asList(elements));
This has the benefit of checking the type at copy time.

Convert Java Array to Iterable

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.

Testing implementation of '<T>' List

I have written my own implementation of java.utils.List. Now I'd like to test it, but I cannot manage to fill my collection with objects since it shows <identifier> expected whenever I add anything :
public static void main(String[] args) {}
MyCollection col = new MyCollection(10);
int[] tab = {1,2,4,5,6};
col.add(tab);
And the whole code here :
http://paste.pocoo.org/show/291343/
EDIT
MyCollection<Integer> col = new MyCollection<Integer>(10);
Integer[] tab = {1,2,4,5,6};
col.add(tab);
still the same :/
You're trying to add an int[] as item of a Collection<Integer> which accepts Integer (or autoboxed int) items only. This would only work if you have a Collection<int[]> (of which the added array would then be the sole item).
To convert an int[] to a Collection<Integer>, you need to loop over it:
int[] array = { 1, 2, 3, 4, 5 };
Collection<Integer> collection = new ArrayList<Integer>();
for (int item : array) {
collection.add(item);
}
See also:
Arrays tutorial
Collections tutorial
Generics tutorial
You're missing your Type. It's a generic class, so it should be something like
MyCollection<Integer> col = new MyCollection<Integer>(10);
Change:
MyCollection<Integer> col = new MyCollection<Interger>(10);
You need to specify the T of your MyCollection.
The generic implications here would not cause an error, you would simply get a warning because any object you add to the list is erased to Object, so you could add any object and would lose type safety.
You have instantiated a list whose members are a single object, whatever the type may be, but you're trying to add an array as a single member. You have a couple of options, but I would stick with:
List<Integer> myCollection = new MyCollection<Integer>(10);
myCollection.addAll(Arrays.asList(1, 2, 3, 4, 5, 6));
If you really intended on have a list of arrays, you would do:
List<Integer[]> myCollection = new MyCollection<Integer[]>(10);
myCollection.add(new Integer[]{1,2,3,4,5,6});
A couple of notes:
Program to the interface (see my example)
Your implementation is called MyCollection, but it's actually an implementation of List, so a name like MyList seems more appropriate unless you plan on actually extending Collection.
I assume this is just an exercise, but I don't see the point in extending List. You know that java.util.ArrayList exists right?

how to define an arrayList with two columns in java?

I have a hashMap. Each "Value"is going to be a a list which will be mapped later on with my "Key"s. List is desired to look like this:
[length,time][length,time][length,time]
For example:
Key{srcAddr=x, dstAddr=y, srcPort=12345, dstPort=80}
value{(6523,0.001),(124,0.05), () , (), ...}
I just wonder how can I have a two-col arrayList.
package myclassifier;
import java.util.ArrayList;
public class FlowStatics {
int packetLength;
double timeArrival;
public FlowStatics(int pLength, double tArrival)
{
this.packetLength = pLength;
this.timeArrival = tArrival;
}
}
and here is how I used it:
final ArrayList<FlowStatics> staticsArray = new ArrayList<FlowStatics>();
final HashMap<Flows, ArrayList> myHashMap = new HashMap<Flows, ArrayList>();
FlowStatics flowStatics = new FlowStatics(packetLength,timeArrival);
staticsArray.add(flowStatics);
myHashMap.put(flows, staticsArray);
and here is the part that I am reading it:
Iterator<Flows> iterator = myHashMap.keySet().iterator();
while(iterator.hasNext()){
Flows key = iterator.next();
ArrayList value = myHashMap.get(key);
System.out.println("Fows"+key+"----------"+"Statics"+ value);
Well, your FlowStatics is the correct solution
List<FlowStatics> will give you the "two-column array list".
Update: as of your update, myHashMap.put(flows, flowStatics); is wrong. You are this putting an individual pair, rather than a list in the map. You should use:
staticsArray.add(flowStatics);
myHashMap.put(flows, staticsArray);
A List<E> is an abstraction for a homogeneous list of elements whose type is E. There are some restrictions (e.g. no primitives), but conceptually the type E can be defined to be whatever you want.
Suppose there's an abstraction of Pair<L,R>. Then a List<Pair<L,R>> is still a list of some E, but now that E is a Pair<L,R>. So it's still a "one-column" list, but each element in the list is a "pair", so it's sort of a "two-column" list.
Note that you don't always need a generic Pair<L,R>. Any type E that properly encapsulates all the information can be used in a List<E>.
And by the way, you can have a List<List<E>> too.
See also
Wikipedia/Encapsulation
Related questions
What is the equivalent of the C++ Pair<L,R> in Java?
List of Lists of Lists
Returning values analogy
Often people ask "How can I return two values in Java?". The answer is analogous. You return one value, a new type which encapsulates both information.
So instead of:
// attempt to return two values
// DOES NOT COMPILE
return "James Bond";
return "007";
You do:
return new SecretAgent("James Bond", "007");
Related questions
Using a java method to return multiple values?

remove duplicates from object array data java

i want to know how to remove duplicates in object.
for example
cat c[] = new cat[10];
c[1].data = "ji";
c[2].data = "pi";
c[3].data = "ji";
c[4].data = "lp";
c[5].data = "ji";
c[6].data = "pi";
c[7].data = "jis";
c[8].data = "lp";
c[9].data = "js";
c[10].data = "psi";
i would like to remove the duplicates value from object array.
thanks and advance
I assume you want to create another array which is duplicate free. (as you cannot change the size of an array)
You could implement hashCode and equals and use a HashSet, however without these you can create a Comparator.
However the simplest approach may be using the "Cat" class and "cats" array
Cat[] cats = { ... };
Set<String> datas = new HashSet<String>();
List<Cat> catList = new ArrayList<Cat>();
for(Cat cat: cats) if(datas.add(cat.data)) catList.add(cat);
Cat[] unqiueCats = catList.toArray(new Cat[catList.size()]);
Something like this should work? Make sure to import java.util.Arrays and java.util.HashSet.
/**
* Removes duplicates from an array. Objects in the array must properly
* implement hashCode() and equals() for this to work correctly.
*/
public static <E> E[] removeDuplicates(E[] array) {
// convert input array to populated list
List<E> list=Arrays.asList(array);
// convert list to populated set
HashSet<E> set=new HashSet<E>();
set.addAll(list);
// convert set to array & return,
// use cast because you can't create generic arrays
return (E[]) set.toArray();
}
You can create another temporary array, loop through the original array, and for each element, check if the value already in the temp array or not. If not, add it in.
You can also use Set and override the equals and hashCode method
Here's a quick hack to do what you wanted to (hopefully also compiles):
// Assuming the code in the question is here.
java.util.List<cat> tmp = new java.util.LinkedList<cat>();
java.util.HashSet<String> set = new HashSet<String>();
for (int i = 0; i < c.length; ++i)
if (set.put(c[i].data)) tmp.add(c[i]);
c = tmp.toArray(c);

Categories