Why doesn't Java allow "new List<T>"? - java

To create a List, why doesn't Java allow them to be created then elements added one by one?
This works:
public static List<TrackedItem> create(List<Item> items)
{
TrackedItem[] arr = new TrackedItem[items.size()];
int i = 0;
for (Item item : items)
{
arr[i] = TrackedItem.createOrUpdate(item);
i++;
}
return java.util.Arrays.asList(arr);
}
This does not work (tracked.add() causes a NullPointerException):
public static List<TrackedItem> create(List<Item> items)
{
List<TrackedItem> tracked = java.util.Collections.emptyList();
for (Item item : items)
{
tracked.add(TrackedItem.createOrUpdate(item));
}
return tracked;
}

java.util.Collections.emptyList();
static
List
emptyList()
Returns the empty list (immutable).
That means, you will not be able to change this list.
Its defined:
static List EMPTY_LIST
The empty list (immutable).
Quotes from Java sun reference
Edit:
To create a new list you could use e.g.
List myList = new ArrayList<MyClass>();

Use the following syntax:
public static List<TrackedItem> create(List<Item> items)
{
List<TrackedItem> tracked = new ArrayList<TrackedItem>();
for (Item item : items)
{
tracked.add(TrackedItem.createOrUpdate(item));
}
return tracked;
}

This might be a misunderstanding.
Even if it is called emptyList, it isn't a list which is just empty and ready to be populated. This emptyList is designed to be empty at all times. You can't add to this special list.
To get a 'usable' empty list you can either
List<String> list = new ArrayList<String>(); // create a new one or
list.add("if you have an list");
list.clear(); // just clear it

create a new arrayList by :
List<T> tracked = new ArrayList<T>();
List is only an interface ... you can't make a new one. you only can implement it.

Related

What is the best approach to split an Arraylist based on their values

I would like to split an ArrayList that I am looping trough and set a field called active which can be true or false. But at the end of loop I would like to split this collection in two groups.. active = false and active = true, so doing this I won't need to search in database twice..
for example:
private List<Classes> searchClasses(ClassItems listItems) {
List<ClassItem> items = new ArrayList<ClassItem>();
for (Iterator<ClassItem> iterator = listItems.getItems().iterator(); iterator.hasNext();) {
ClassItems item = iterator.next();
ClassEntityManager classEnt = ClassEntityManager.search(item.getId);
if(classEnt.active()){
item.setActive(true);
items.add(item);
}
}
return items;
}
What is the best approach to do this??
Make two lists instead of one.
if(classEnt.active()) {
activeItems.add(item);
item.setActive(true);
} else {
inactiveItems.add(item);
}
Use two collections, one for actives and the other for not actives.
When you fetch the data from the DB, simply put the CalssItem in the correct list:
private List<ClassItem> searchClasses(ClassItems listItems) {
List<ClassItem> activeItems= new ArrayList<ClassItem>();
List<ClassItem> notActiveItems= new ArrayList<ClassItem>();
Iterator<ClassItem> i = listItems.getItems().iterator();
while(i.hasNext()) { //This is a better approach.
ClassEntityManager classEnt = ClassEntityManager.search(i.next().getId);
if(classEnt.active()){
item.setActive(true);
activeItems.add(item);
}else{
item.setActive(false);
notActiveItems.add(item);
}
}
List<ClassItem> ret = new ArrayList<ClassItem>(activeItems);
ret.addAll(notActiveItems);
return ret;
}
BUT, in this way, both activeItems and notActiveItems are unreacheable. Best thing to do is to have a loop outside your method that checks if the ClassItem is active or not. In this way both activeItems and notActiveItems can be deleted from the method:
private List<ClassItem> searchClasses(ClassItems listItems) {
List<ClassItem> items= new ArrayList<ClassItem>();
Iterator<ClassItem> i = listItems.getItems().iterator();
while(i.hasNext()) { //This is a better approach.
ClassEntityManager classEnt = ClassEntityManager.search(i.next().getId);
item.setActive(classEnt.active());
items.add(item);
}
return items;
}
And to use the list:
List<ClassItem> items = searchClasses(classItems);
for(ClassItem item: items){
if(item.isActive()){
//do something
}else{
//do something else
}
}
Better yet is to use the magnificient and beautiful Java 8 Stream API:
List<ClassItem> active = items.stream().filter(x->x.isActive).collect(Collectors.toList());
List<ClassItem> notActive = items.stream().filter(x->!x.isActive).collect(Collectors.toList());
or the one liner:
List<ClassItem> active = searchClasses(classItems).stream().filter(x->x.isActive).collect(Collectors.toList());
NOTES:
Your code has a return type of List<Classes>, while the returned value is of List<ClassItem>. Which is right?
Your iterator has a generic type of ClassItem while the next() method returns a ClassItems object. Which is right?

Linked list addBegnining with parameterized list

I've wrote a method in my implementation of my interface that takes a linked list in parameter and has to return an arraylist of all the items that exists already and weren't added to the class list.
Here's the signature:
public List<T> addBegining(ListeOfEmployees<T> list);
My methode add's the elements in the linked list of the class in inverse.
Lets say the parameter list:
Employee1
Employee2
Employee3
Employee4
Employee5
Actual list in the class:
Employee2
Employee4
Employee5
It's suppose to return an ArrayList in the same order of the parameter list:
1-Employee2
2-Employee4
3-Employee5
But it returns an ArrayList like this:
1-Employee5
2-Employee4
3-Employee2
I used a while() to cycle thru my parametered list but it goes from begining to end.
I don't know how I can cycle thrue the parameterized list but from the end to the beginning.
I cannot use a pointer at the end of the list for this method.
I'm out of solutions here.
Here's what i've done so far:
public List<T> addBegining(ListeOfEmployees<T> list) {
List<T> res = null;
T return;
Iterator<T> it = list.iterator();
while (it.hasNext() && list != null) {
return = it.next();
if (this.hasElement(return)) {
if (res == null) {
res = new ArrayList<T>();
}
res.add(retour);
} else {
this.addBegining(retour);
nbElm++;
}
}
return res;
}

How to keep adding values to a List using a JButton and JTextArea without them being re-written

private void addButtonActionPerformed(java.awt.event.ActionEvent evt) {
String newCD = (cdInput.getText());
List <String> cdList = new ArrayList();
Collections.addAll(cdList, "ExampleG","ExampleB","ExampleR","ExampleX");
cdList.add(""+newCD);
List<String> sorted = new ArrayList<String>(cdList);
Collections.sort(sorted);
bigBox.setText("");
bigBox.append("Original Order\n**************\n");
for (String o : cdList) {
bigBox.append(o);
bigBox.append("\n");
}
bigBox.append("\n\nSorted Order\n************\n");
for (String s : sorted) {
bigBox.append(s);
bigBox.append("\n");
}
}
With this code, I can add 1 value, but when I try to add another one, it erases the original and replaces it. What can I do to prevent this?
PS. I'm trying to make a List of CDs, and be able to add new ones and have them also sorted and put in thier original order
Based on your code, you have no centralised instance of List, which means, each time you activate the button, it has no concept of what was previously in the list.
Start by creating an instance variable of the cd List and only add new items to it as required.
Something more like...
private List<String> cdList = new ArrayList<>(25);
private void addButtonActionPerformed(java.awt.event.ActionEvent evt) {
String newCD = (cdInput.getText());
cdList.add(newCD);
List<String> sorted = new ArrayList<String>(cdList);
Collections.sort(sorted);
bigBox.append("Original Order\n**************\n");
for (String o : cdList) {
bigBox.append(o);
bigBox.append("\n");
}
bigBox.append("\n\nSorted Order\n************\n");
for (String s : sorted) {
bigBox.append(s);
bigBox.append("\n");
}
}

split an array list into multiple lists in java

I have an array list which when populated has a key and a value I want to know if there is a way of splitting it on repeating keys for example my current data is like this:
[RoleID_123.0, UserHandel_tom, Password_12345.0, prevPassword_null, userCaption_thomas, Email_tom#tom.tom, RoleID_124.0, UserHandel_dave, Password_ghadf, prevPassword_sdfsd, userCaption_david, Email_dave#dave.dave, RoleID_125.0, UserHandel_trevor, Password_tre, prevPassword_null, userCaption_trev, Email_trev#trev.trev]
I want it to come out more like this:
[RoleID_123.0, UserHandel_tom, Password_12345.0, prevPassword_null, userCaption_thomas, Email_tom#tom.tom]
[RoleID_124.0, UserHandel_dave, Password_ghadf, prevPassword_sdfsd, userCaption_david, Email_dave#dave.dave]
[RoleID_125.0, UserHandel_trevor, Password_tre, prevPassword_null, userCaption_trev, Email_trev#trev.trev]
Is there a way to split it on say role id or am I going about this the wrong way?
You can try by using HashMap
private static class MyItemHashMap extends HashMap {
public Item add(Item item) {
get(item).add(item);
return item;
}
public List get(Item key) {
List list = (List) get(createItemKey((Item) key));
return list == null ? createItemEntry((Item) key) : list;
}
private List createItemEntry(Item item) {
List list = new ArrayList();
put(createItemKey(item), list);
return list;
}
private Object createItemKey(Item item) {
return item.getSplitterProperty();
}
}
public static void main(String[] args) {
MyItemHashMap itemMapped = new MyItemHashMap();
List items = Arrays.asList(new Object[]{new Item("A"), new Item("B"),
new Item("C")});
for (Iterator iter = items.iterator(); iter.hasNext();) {
Item item = (Item) iter.next();
itemMapped.add(item);
}
}
If it is an ArrayList, there is no built-in function to split data like this; you will have to do it manually. If you know the number of consecutive fields that make a single structure, this shouldn't be too hard; something like this:
// 6 because there are 6 fields
for (int i = 0; i < arrayList.size(); i = i + 6) {
List thisList = arrayList.subList(i, i + 5);
// ... Now do whatever you want with thisList - it contains one structure.
}
If the number of fields can change then you'll have to do something a little more dynamic and loop through looking for a RoleID field, for example.
I'd use a HashMap to seperate the data instead of one long ArrayList ( you shouldn't have stored the data like this in the first instance )
HashMap<String,ArrayList<String>> hm = new HashMap<String,ArrayList<String>>;
// For each list:
ArrayList<String> arr = new ArrayList<String>;
arr.add("each element");
hm.put("RoleID_123.0", arr);
This way you will end up with a three dimensional structure with a key ( "RoleID..." ) pointing to its child elements.
Try this
String[] str=new String[]{"RoleID_123.0", "UserHandel_tom", "Password_12345.0", "prevPassword_null", "userCaption_thomas", "Email_tom#tom.tom", "RoleID_124.0", "UserHandel_dave", "Password_ghadf", "prevPassword_sdfsd", "userCaption_david", "Email_dave#dave.dave", "RoleID_125.0", "UserHandel_trevor", "Password_tre", "prevPassword_null", "userCaption_trev", "Email_trev#trev.trev"};
List<String> list=new ArrayList<>(Arrays.asList(str));
List<String> subList=list.subList(0,5);
You can try something similar to this
If you feel like taking a Linq-ee Libraried approach, this is about as good as it gets, and it requires use of a couple delegate objects:
import static com.google.common.collect.Collections2.filter;
import static com.google.common.collect.Collections2.transform;
//...
final List<String> yourList = //...
final int RECORD_LENGTH = 6;
Collection<String> roleIdValues = filter(yourList, new Predicate<String>() {
public boolean apply(#Nullable String input) {
return input != null && input.startsWith("RoleID");
}
});
Collection<Collection<String>> splitRecords = transform(roleIdValues, new Function<String, Collection<String>>() {
#Nullable public Collection<String> apply(#Nullable String input) {
return yourList.subList(yourList.indexOf(input), RECORD_LENGTH);
}
});
If Oracle had delivered Java 8 on time you would be able to do this in a way more slick manor. Ironically the reason you cant was provided by the same people providing the guava library

Collections - clear()

I have created a collection and filled it with elements which are collections too, but when I tried to iterate through this container using a foreach construction (or other methods) it returns me nothing, I tried to get size() and saw what I expect (appropriate number) but seems like nevertheless container not empty inside each collection is null
Code snippet example:
Item it1, it2;
List<Collection<Item>> hull = new ArrayList<Collection<Item>>();
List<Item> seq = new ArrayList<Item>();
seq.add(it1);
hull.add(seq);
seq.clear();
seq.add(it2);
hull.add(seq);
for (<Collection<Item> c: hull)
System.out.println(c);
This is just an simplified snippet of what I do
Please suggest alternatives. Where did I make a mistake?
Each time you call seq.clear() you empty the inner ArrayList. Don't forget that when you add an object to a Collection, you only add the reference. You don't clone the Object. You should create a new ArrayList Object at each iteration.
E.g.
List<Collection<Item>> hull = new ArrayList<Collection<Item>>();
List<Item> seq = new ArrayList<Item>();
seq.add(it1);
hull.add(seq);
List<Item> seq2 = new ArrayList<Item>();
seq2.add(it2)
hull.add(seq2);
EDIT:
Complete Sample that compiles:
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class NewClass1 {
static class Item {
String a;
public Item(String a) {
this.a = a;
}
#Override
public String toString() {
return a;
}
}
public static void main(String[] args) {
List<Collection<Item>> hull = new ArrayList<Collection<Item>>();
List<Item> seq = new ArrayList<Item>();
Item it1 = new Item("item 1");
seq.add(it1);
hull.add(seq);
List<Item> seq2 = new ArrayList<Item>();
Item it2 = new Item("item 2");
seq2.add(it2);
hull.add(seq2);
for (Collection<Item> current : hull) {
for (Item item : current) {
System.out.println(item);
}
}
}
}
Output:
run:
item 1
item 2
Your code, corrected to compile:
package sample;
import java.util.ArrayList;
import java.util.List;
public class Item {
public static void main( String[] args ) {
List< List< Item >> hull = new ArrayList<>();
List< Item > seq = new ArrayList<>();
seq.add( new Item());
hull.add( seq );
seq = new ArrayList<>(); // in place of seq.clear();
seq.add( new Item());
hull.add( seq );
for( List<Item> c: hull ) {
System.out.println( c.get( 0 ));
}
}
}
ouputs:
sample.Item#6da264f1
sample.Item#40914272
As you can see, there is no problem.
In order to iterate through a collection of collections you need a nested foreach.
for(Collection<Item> c: hull)
{
for(Item i: c)
{
}
}
By the way, are you aware that it1 and it2 are not initialized and that's why you are getting nothing?
size() will always give you the size of the collections, but they might be containing nulls (as it is your case).

Categories

Resources