First of all i have little experience in Java.
Getting to my question, I am implementing my own list with my own methods.
public class MyList<E> implements List<E>{
.....
One of this methods returns the size of my list
public int getSize(){
....
}
Then I have two other methods that would be more simple if I could somehow apply this method to my list. How so?
I have a method that has to compare if a given list is equal to this list
public boolean equals(Lista<E> list){
....
}
I had though about first comparing the size of both list, and if they don't match it returns false. if they do, it continues to compare each element. Is this possible? How would I applied getSize ? If this is not possible, i will just compare element by element.
My other method has to return an array of each element
public Object[] toArray() {
E myarray = new E[??]
As you can see, i dont' know how to declare this array. I would have to know beforehand the size of my list. I though about passing as an argument (which would solve the problem) but i need to solve it this way.
You call list.getSize(), like so:
if (list.getSize() != this.getSize()) {
return false;
}
Since you cannot create generic array in Java, you would have to do
public Object[] toArray() {
E[] myarray = (E[]) new Object[this.getSize()];
Simply use the getSize() method:
E myarray = new E[getSize()];
Related
When I create a method to determine what value I want to return, usually I can return a value directly - like so:
return 0;
However, I've discovered that when returning arrays, I have to create a new instance of an array, and return it - like so:
String[] rtnArr = {"str1", "str2"};
return rtnArr;
Why is this? Am I creating two arrays here, or am I only specifying a type when I instantiate the method?
Edit: I should clarify that I am returning one or another array based on a preliminary condition. That is to say, I have a switch and each case returns an array of different strings.
You are not creating two arrays. Array initializers are only allowed when initiating a variable, so you can't use them directly in a return statement.
You don't actually need a variable to return an array. You can also return an array like this
return new String[] {"Hello", "World"};
When you declare an array you can initialize it as String test[] = {"Hello", "World"}; because the array is obviously a string array so you don't need to do new String[] {"Hello", "World"}, but otherwise, you need an explicit initialization of the array with a type for type safety.
I've discovered that when returning arrays, I have to create a new instance of an array, and return it Why is this ? Am I creating two arrays here, or am I only specifying a
type when I instantiate the method ?
You don't need to return a new instance of the array always, sometimes you might need to return an existing array object as shown in the below code:
public class MyArrayTest {
private String[] myArray;
public MyArrayTest(String[] myArray) {
this.myArray = myArray;
}
public String[] getMyArray() {
return myArray;//returning existing array object
}
}
I have a similar cases with one of the user that posted a question before. It is a card game, and we have to create a new data type called card where it contains "rank" and "suit".
How to get the size of arrayList of card when we can't use size() or length since it is not a string?
Update: I can't use size() because when I write it, it will gives warning cannot resolve method 'size()'
`ArrayList<Card> hisCards;
hisCards = new ArrayList<Card>();`
public static int checkColumn(Card cardArray) {
int cardSize = cardArray.size();
if (cardSize == 0) {
return 1;
}
return 0;
}
I'm just planning to pass it through a function later. cardArray will be substituted by hishand
Maybe I'm just doing it wrong?
Update: I can't use size() because when I write it, it will gives warning cannot resolve method 'size()'
Ensure you are invoking the size() method from the correct instance. This is an example of how you can get the size from an arraylist:
ArrayList<Card> hisCards = new ArrayList<Card>();
int numOfCards = hisCards.size(); //get number of elements from hisCards
Edit: You are invoking size() on a Card object instead of an arraylist !
Change your method to:
public static int checkColumn(ArrayList<Card> cardArray)
The size() method is not a method of String, it's a method of Collection, which means that new ArrayList<Card>().size() is valid.
The size()-method returns the number of elements in the collection.
With your code example, hisCards.size() should not result in a compilation error.
Your variable named cardArray is not an array(or an ArrayList), it's just a Card. Of course, this has no size()-method (unless you actually made one.)
I am new to java and I was writing some code to practice, but there is something that I am confused about. I have the following code:
public class test {
public static void main(String[]args) {
int n = 0;
ArrayList<String> fruits = new ArrayList();
setList(fruits);
n =setInt(9);
// get the values from fruits
for (String value: fruits) {
print(value);
}
}
public static void setList( ArrayList list) {
list.add("pear");
list.add("apple");
list.add("pear");
}
public static int setInt(int number) {
number = 3;
return number;
}
}
My question is why in order to set my Arraylist() there is no need to return the any value, but in order to set my int I need to return something.If run this code it prints all the values in my list, but I expected not to print anything because In my method setList I do not return any value. If I did not return any value with my setInt, the value of n would not change, and that makes sense to me.
Thank you.
There are different ways to that params get passed in functions. The usuall way that most beginners start with is pass by value. The other way is pass by reference. In passing by reference, the object itself is pass in, not a copy as is with pass by value. That means any changes will affect the param and remain, even after it is called. All objects in java are passed by reference, only primitives are passed by value. Thus, is why you don't have to return when using arraylist object.
Edit: Actually, I've made an error. What is actually occuring is that a copy of the reference itself is being passed by value. Take a look at this.
Everything in Java is Pass by Value.
EDIT: This is NOT a duplicate of the above question. The original question concerns a list whose type is unknown at compile time. This question concerns an array like construct of a generic list.
For example the above solution of final E[] a = (E[]) Array.newInstance(c, s); won't work because I can not obtain List<MyClass>.class And also you can't cast from Object[] to List<MyClass>[]
What is the idiomatic way to deal with an array like construct of generic type? For example, I want an array of List<MyClass>. ArrayList<List<MyClass>> myClassArray won't work directly because I need to be able to do things like myClassArray.set(5, myClassObj) even when the myClassArray.size() is 0. Initialize it with
for(int i = 0; i < mySize; i ++){
myClassArray.add(null)
}
works but it's ugly.
List<MyClass> myClassArray[] won't work either because you can't create a generic array. So what is the most idiomatic way to achieve my goal? The size of array won't change once created.
Create your own class to simulate an array.
class Array<T> {
final Object[] data;
public Array(int size) {
data = new Object[size];
}
public void set(int index, T datum) {
data[index] = datum;
}
#SuppressWarnings("unchecked")
public T get(int index) {
return (T) data[index];
}
}
Since you control the access to the underlying array, you know that the elements in there will all be of type T.
The usual way is
List<MyClass>[] myClassArray = new List[size];
The reason why the type of array of parameterized types is "unsafe" is very obscure (because arrays are supposed to check at runtime when you put something into it that it's an instance of the component type, but it's not possible to actually check the parameter for a parameterized type) and not relevant for your purposes.
I have a list. The list can contain multiple items of the same enum type.
Lets say i have an enum : TOY which has values: BALL, DOLL, PLAYSTATION. I want to know how many PLAYSTATION items are in a list with the type TOY. (ie, List<Toy> toys)
What is the best possible solution for this? I don't want to keep iterating through the list everytime.
You can use Apache commons-collections' HashBag. It has a getCount(Object) method which will suit you.
java.util.Collections has a method called frequency(Collection c, Object type).
Usage in my question:
int amountOfPlayStations = Collections.frequency(toys, TOY.PLAYSTATION);
Why don't you create a decorator for the type of list you're using which stores a list of counts for each enum type have been added/removed internally. That way you could use it as a normal list but also add some extra functionality for querying how many of which type are currently contained.
All you'd need to do would be to override the add/remove/addAll etc methods and increment your counters before passing it on to the real list type. The best part about it would be that you could decorate any list type with your new wrapper.
At the very least, a utility method like:
public int count(List<Toy> haystack, Toy needle) {
int result;
for (Toy t : haystack) {
if (t == needle) {
result++;
}
}
return result;
}
Would let you concisely refer to the number of PLAYSTATIONs from elsewhere in the code. Alternatively if you knew the list was unlikely to change, building a Map<Toy, Integer> would let you build up the counts for all items once.
If you don't want to have to iterate over the entire collection each time, another alternative would be to write a ForwardingList implementation. The main benefits of this over the HashBag suggestion are:
it supports generics
it implements the List interface, so you can pass it to any method that expects a List
There is a downside to this approach however, in that you have to write a bit of plumbing code to get it up and running.
Below is a quick example of how you could do it. Note that if you do this you should override all methods that add/delete from the list, otherwise you may end up in an inconsistent state:
import com.google.common.collect.ForwardingList;
public class CountingList<E> extends ForwardingList<E> {
private List<E> backingList = new LinkedList<E>();
private Map<E, Integer> countMap = new HashMap<E, Integer>();
#Override
protected List<E> delegate() {
return backingList;
}
#Override
public boolean add(E element) {
backingList.add(element);
if(countMap.containsKey(element)) {
countMap.put(element, countMap.get(element) + 1);
} else {
countMap.put(element, 1);
}
return true;
}
public int getCount(E element) {
Integer count = countMap.get(element);
return count != null ? count.intValue() : 0;
}
}
Extend java.util.List method and override all mutator methods, i.e. the ones that are used for add or delete elements and also ones used to clear the list. Add a reference to a private java.util.Map which will hold the number of items per type. Add accessor methods which will return current number of elements per type.
The HashBag (by Bozho) seems to be your best bet. But a bit more general would be Googles Collections 2 with an appropriate Predicate:
List<Toy> toys;
List<Toy> playstations = Collections2.filter( toys, new Predicate() {
boolean apply(TOY toy){
return toy == TOY.PLAYSTATION;
}
});
Besides all those solutions (I have a weakness for the Collections.Frequency call), i would recommend you to take a look at google collections, and particularly to [Collections2.transform][2], which could give you a live view on items.
[2]: http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/Collections2.html#transform(java.util.Collection, com.google.common.base.Function)