Arraylist of classes - java

In my hw assignment my professor says to create a data field of type ArrayList. He wants them to be instances of a class.
I'm not exactly sure what that means, but my guess is
ArrayList<CLassName> list = ArrayList<ClassName>();
Can anyone confirm this for me?

You can use something like this:
List<String> list = new ArrayList<String>();
Since Java SE 1.7, it can a little simpler:
List<String> list = new ArrayList<>();

Yes.
NOTE: The rest is background knowledge about ArrayLists.
Let's say you want an ArrayList of Strings. Keep in mind Strings are Objects.
// Creates ArrayList
ArrayList<String> list = ArrayList<String>();
// Adds elements to ArrayList
list.add("Hello");
list.add("world!");
// Iterate through ArrayList
for (String str : list) {
// Print the String in the list.
System.out.print(str + " ");
}
// Print newline character.
System.out.print("\n");
The for (String str : list) is a for each loop which allows you to iterate through each element in the list.

Yes, that's right. I do, however, recommend this instead:
List<ClassName> list = new ArrayList<ClassName>();
That way you can change the type of list in just one place instead of two.

Related

Converting List<List<String>> to array

I have elements that is declared in a list variable such as:
List<List<String>> textList = new ArrayList<>();
The elements are added such as:
textList.add(Arrays.asList(p)); //adding elements
The only way I could output the elements inside the variable is by using:
for(List<String> s: textList){
System.out.println(s); }
which output elements like this:
[He is a boy.]
[He likes apple.]
[She is a girl.]
Now, I would like to store them in an array so that the elements will look like this when outputted.
[He is a boy., He likes apple., She is a girl.]
I've tried
String[] textArr = new String[textList.size()];
textArr = textList.toArray(textArr);
for(String s : textArr){
System.out.println(s);}
but I got an error about:
Exception in thread "main" java.lang.ArrayStoreException
at java.lang.System.arraycopy(Native Method)
at java.util.Arrays.copyOf(Arrays.java:3213)
at java.util.ArrayList.toArray(ArrayList.java:407)
So, how do I convert the elements inside a list into array using the proper way. Thanks!
Your problem is that you are not storing Strings in your list textList.
textList.add(Arrays.asList(p));
As the type says, you have a List of List of String here.
So you can't take the elements of that list and assume they are Strings. Because they aren't! The error message tells you that: toArray() wants strings it can put into that array of strings, but you give it a List of List of String!
But thing is: what you are describing here doesn't make sense in the first place. Printing strings shouldn't care if strings are in an array or a List.
What I mean is: when you manually iterate a List or an array to print its content, then it absolutely doesn't matter if you iterate a List or an array. The code is even the same:
for (String someString : someCollection) {
System.out.println(someString);
}
someCollection can be both: array or List!
In other words: the idea to turn data that is nicely stored within Lists into arrays for printing simply doesn't make any sense. To the contrary: you are probably calling toString() on your List object, and the result of that ... isn't 100% what you want. But I guarantee you: calling toString() on some array will result in something you totally will not want.
Long story short: forget about converting to Arrays; simply iterate your List of List of Strings and use a StringBuilder to collect the content of that collection the way you want to see it (you simply append those [ ] chars to that builder in those places you want them to see).
(if you insist on that conversion to array, the key point there to understand is that only a List of String can be turned into an array of string. So a List of List ... doesnt work that easy).
Using streams and flatMap, you can do this:
List<List<String>> list = ...;
String[] strings = list.stream().flatMap(l -> l.stream()).collect(Collectors.toList()).toArray(new String[0]);
This is equivalent to using a loop (You can use two nested for loops as suggested in the comments instead by replacing the addAll, but why?):
List<List<String>> list = ...;
List<String> stringList = new ArrayList<>();
for (List<String> l : list)
stringList.addAll(l);
String[] strings = list.toArray(new String[stringList.size()]);
You can use Iterator in order to go over every element of the list, instance of the for each statement (I personally like the iterators more). The code you could use would be something like
//Your list
List<List<String>> textList = new ArrayList<>();
//The iterators
Iterator<List<String>> itList = textList.iterator();
Iterator<String> itString;
//The string to store the phrases
String s[] = new String[textList.size()];
int i =0;
//First loop, this seeks on every list of lists
while(itList.hasNext()){
//Getting the iterator of strings
itString = itList.next().iterator();
s[i] = "";
//2nd loop, it seeks on every List of string
while(itString.hasNext()){
s[i] = s[i].concat(itString.next());
}
s[i] = s[i].concat(".");
i++;
}

Inserting a String[] into a String[] in Java?

How do you add a String[] into a String[] in Java? To be more clear, my desired output is:
String[][] out = {{"A", "AA"},{"B", "BB"}};
I don't know the size of the output array, it can contain more then two elements. Basically, I wanted to do it like this (don't mind the syntax it's a blend of Python):
String [] out;
String[] temp = {"A","AA"};
out.append(temp)
So now out should look like {{"A","AA"}}. Then I can append {"B", "BB"} creating the desire output above? This is what my thought was, but I'm not sure if it can be done. I am more experienced with Python and it can be done in Python, but I am wanting to do this in Java. Any ideas?
As in the comment mentioned, you can use the List to store all the array values inside.
It is when you put in:
List<String[]> list = new ArrayList<>();
String[] array = {"A", "B"};
list.add(array);
...
And it is when you get out:
String[] array = list.get(0 /*i*/);
Try using List for this purpose as you would have more operations to perform on Lists than an Array.
List<List<String>> out = new ArrayList<>();
List<String> temp = new ArrayList<String>();
temp.add("A");
temp.add("AA");
out.add(temp);
Read through the Javadocs for more on this.
You can either use List or ArrayList that dynamically grows.
ArrayList al = new ArrayList();
The ArrayList class extends AbstractList and implements the List interface. ArrayList supports dynamic arrays that can grow as needed.
Standard Java arrays are of a fixed length. After arrays are created, they cannot grow or shrink, which means that you must know in advance how many elements an array will hold.
Array lists are created with an initial size. When this size is exceeded, the collection is automatically enlarged. When objects are removed, the array may be shrunk.
For differences between List and ArrayList Type List vs type ArrayList in Java
Detailed Methods of ArrayList
You could try this way too if you exactly want to add dynamic array of Strings into another dynamic array.
List<List<String>> addresses = new ArrayList<List<String>>();
ArrayList<String> singleAddress = new ArrayList<String>();
singleAddress.add("17 Fake Street");
singleAddress.add("Phoney town");
singleAddress.add("Makebelieveland");
addresses.add(singleAddress);
Because in Java, Array is a fixed length data structure so you should try java List which supports dynamically insertion and deletion of elements. An example using java.util.ArrayList is following:
java.util.List<String[]> out = new java.util.ArrayList<String[]>();
String[] temp = {"A","AA"};
out.add(temp);//insertion
And using index (started from 0), we can get element like out.get(0); and can remove element like out.remove(0);

Add multiple numbered objects to ArrayList

Suppose I have a lot of String Variables(100 for example):
String str1 = "abc";
String str2 = "123";
String str3 = "aaa";
....
String str100 = "zzz";
I want to add these String variables to ArrayList, what I am doing now is
ArrayList<String> list = new ArrayList<String>();
list.add(str1);
list.add(str2);
list.add(str3);
...
list.add(str100);
I am curious, is there a way to use a loop? For example.
for(int i = 1; i <= 100; i++){
list.add(str+i)//something like this?
}
Use an array:
String[] strs = { "abc","123","zzz" };
for(int i = 0; i < strs.length; i++){
list.add(strs[i]); //something like this?
}
This idea is so popular that there's built-in methods to do it. For example:
list.addAll( Arrays.asList(strs) );
will add your array elements to an existing list. Also the Collections class (note the s at the end) has static methods that work for all Collection classes and do not require calling Arrays.asList(). For example:
Collections.addAll( list, strs );
Collections.addAll( list, "Larry", "Moe", "Curly" );
If you just want a list with only the array elements, you can do it on one line:
List<String> list = Arrays.asList( strs );
Edit: Many other classes in the Java API support this addAll() method. It's part of the Collection interface. Other classes like Stack, List, Deque, Queue, Set, and so forth implement Collection and therefore the addAll() method. (Yes some of those are interfaces but they still implement Collection.)
If you are using Java 9 then easily you can add the multiple String Objects into Array List Like
List<String> strings = List.of("abc","123","zzz");
If you want to stick to good practice, declare your Strings in an array:
String[] strs = new String[]{ "abc", "123", "aaa", ... };
for (String s : strs) // Goes through all entries of strs in ascending index order (foreach over array)
list.add(s);
If strX would be class fields then you could try using reflection - link to example of accessing fields and methods.
If it is local variable then you can't get access to its name so you will not be able to do it (unless str would be array, so you could access its values via str[i] but then you probably wouldn't need ArrayList).
Update:
After you updated question and showed that you have 100 variables
String str1 = "abc";
String str2 = "123";
String str3 = "aaa";
//...
String str100 = "zzz";
I must say that you need array. Arrays ware introduced to programming languages precisely to avoid situation you are in now. So instead of declaring 100 separate variables you should use
String[] str = {"abc", "123", "aaa", ... , "zzz"};
and then access values via str[index] where index is value between 0 and size of your array -1, which in you case would be range 0 - 99.
If you would still would need to put all array elements to list you could use
List<String> elements = new ArrayList<>(Arrays.asList(str));
which would first
Arrays.asList(str)
create list backed up by str array (this means that if you do any changes to array it will be reflected in list, and vice-versa, changes done to list from this method would affect str array).
To avoid making list dependant on state of array we can create separate list which would copy elements from earlier list to its own array. We can simply do it by using constructor
new ArrayList<>(Arrays.asList(str));
or we can separate these steps more with
List<String> elements = new ArrayList<>();//empty list
elements.addAll(Arrays.asList(str));//copy all elements from one list to another
Yes. The way to use a loop is not to declare 100 string variables. Use one array instead.
String[] str = new String[101];
str[1] = "abc";
str[2] = "123";
str[3] = "aaa";
....
str[100] = "zzz";
(I made the indexes go from 1 to 100 to show how it corresponds to your original code, but it's more normal to go from 0 to 99 instead, and to initialize it with an array initializer as in #markspace's answer.)
The following creates the ArrayList on the specific String values you have:
ArrayList<String> list1 = new ArrayList<String>() {{addAll(Arrays.asList(new String[]{"99", "bb", "zz"}));}};
Or, if it's just some distinct values you want, use this for say - 10 of them:
ArrayList<String> list2 = new ArrayList<String>() {{for (int i=0; i<10; i++) add(""+System.currentTimeMillis());}};

Java. How to delete duplicate objects from both Lists

2nd question, which is continue of first.
I have got two Lists of strings. There is an List of strings (asu) - M1, M2, M3 ... As well as an List of string (rzs) - M1, M2, M3 and all possible combinations thereof. The need for each element (asu) (for example M1) to find an element in (rzs) (M1, M1M2, ..), which contains (e.g. M1). Example: took M1 from (asu) and will start search for duplicate(contain) in (rzs). We found M1M2 in (rzs), it contains M1. After that we should delete both elements from lists. Great thanks to No Idea For Name helped for modification this code. But the program always fails because AbstractList.remove error. Please help to implementation logic and tuning code!
Imports..........
public class work{
List<string> asu = Arrays.asList("M1","M1","M1","M3","M4","M5","M1","M1","M1","M4","M5","M5");
List<string> rzs = Arrays.asList("M1","M2","M3","M4","M5",
"M1M2","M1M3","M1M4","M1M5","M2M3","M2M4","M2M5","M3M4","M3M5","M4M5"
,"M1M2M3","M1M2M4","M1M2M5","M1M3M4","M1M3M4","M1M4M5","M2M4","M2M5");
public static void main(String[] args) {
work bebebe = new work();
bebebe.mywork();
}
List<string> tmp1 = new ArrayList<string>();
List<string> tmp2 = new ArrayList<string>();
System.out.println(Arrays.deepToString(rzs));
System.out.println(Arrays.deepToString(asu));
for (string curr : asu){
for (string currRzs : rzs){
System.out.println("New iteration ");
if (currRzs.contains(curr)) {
System.out.println("Element ("+curr+") in ASU =
element ("+currRzs+") in RZS");
if(tmp1.contains(curr) == false)
tmp1.add(curr);
if(tmp2.contains(currRzs) == false)
tmp2.add(currRzs);
}
}
}
for (string curr : tmp1){
asu.remove(curr);
}
for (string currRzs : tmp2){
rzs.remove(currRzs);
}
You should try to make use of removeAll() or retainAll() methods of Collection.
For example:
List<String> aList = new ArrayList<String>();
aList.add("a");
aList.add("b");
aList.add("c");
aList.add("d");
aList.add("e");
List<String> bList = new ArrayList<String>();
bList.add("b");
bList.add("e");
bList.add("d");
aList.removeAll(bList);
will give you the "a" and "c" elements left in aList
While if you try to make use of retainAll() method:
aList.retainAll(bList);
will give you "b", "d" and "e" elements left in aList;
retainAll() is used to remove all the elements of the invoking collection which are not part of the given collection.
removeAll() is used to remove all the elements of a collection from another collection.
So, it all depends on your use-case.
EDIT
If in any case you want to remove some elements from these collections while iterating conditionally then you should first obtain the Iterator<Type> then call the remove() method over it.
Like:
while(iterator.hasNext()){
String str = iterator.next();
if(str.equals('test')){
iterator.remove();
}
}
Don't remove items from list using foreach loop. Use classic for and iterate over elements, and when removing item, decrease iterator.
To safely remove elements while iterating use Iterator.remove method:
The behavior of an iterator is unspecified if the underlying
collection is modified while the iteration is in progress in any way
other than by calling this method.
Iterator<String> i = tmp1.iterator();
while (i.hasNext()) {
i.next(); // must be called before remove
i.remove();
}
Also it is easier to remove all collection from another by simply calling:
asu.removeAll(tmp1);
instead of List you can use Set, which will remove automatically the duplicate elements...
You can use removeAll() method to remove collection of elements from the list instead of removing one by one.
use
asu.removeAll(tmp1);
instead of
for (string curr : tmp1)
{
asu.remove(curr);
}
and use
rzs.removeAll(tmp2);
instead of
for (string currRzs : tmp2)
{
rzs.remove(currRzs);
}
update
I trace out your problem.The problem lies in Arrays.asList() method.
According to Arrays#asList
asList() returns "a fixed-size list backed by the specified array". If you want to resize the array, you have to create a new one and copy the old data. Then the list won't be backed by the same array instance.
So create a duplicate ArrayList for the lists.Like this
List<string> asuDuplicat = new ArrayList<string>(asu);
List<string> rzsDuplicat = new ArrayList<string>(rzs);
use asuDuplicat,rzsDuplicat.
asuDuplicat.removeAll(tmp1);
rzsDuplicat.removeAll(tmp2);

Java Get Multiple Items From Collection

Do Java collections have a built-in method to return multiple items from that collection? For example, the list below has n elements, some of which are duplicated in the list. How could I get all elements where the value = "one"? I realize it would be very easy to write my own method to achieve such functionality, I just wanted to make sure I am not missing a built in method to do this.
List<String> ls=new ArrayList<String>();
ls.add("one");
ls.add("two");
ls.add("three");
ls.add("one");
ls.add("one");
//some type of built in function????
//ls.getItems("one");
//should return elements 0,3,4
Thanks
Google Collections have Predicates for this purpose.
In this example, it's enough to know the number of times "one" appears in the list, which you can get with java.util.Collections.frequency(ls, "one").
You could also have been using a Multiset from google-collections, and called m.count("one"), which would be much more efficient.
There isn't a built-in method, but Apache Commons has a select method in CollectionUtils that will get all the elements that match some criterion. Example usage:
List<String> l = new ArrayList<String>();
// add some elements...
// Get all the strings that start with the letter "e".
Collection beginsWithE = CollectionUtils.select(l, new Predicate() {
public boolean evaluate(Object o) {
return ((String) o).toLowerCase().startsWith("e");
}
);
I think you could do the trick of retaining the elements of this list which are in another list with the retainall method of Collection class link text. In the other list you can add only the "one" object.
List<String> ls=new ArrayList<String>();
ls.add("one");
ls.add("two");
ls.add("three");
ls.add("one");
ls.add("one");
List<String> listToCompare = new ArrayList<String>();
listToCompare.add("one");
ls.retainAll(listToCompare);

Categories

Resources