List of Lists of Lists - java

I'm new to Java and I need to make a list of lists of lists. I could do it in python because an element of a list can be a list so in an embedded list list[0] would refer to a list and list[0][0] would refer to the zeroeth element of the embedded list. Is there any easy way to implement this behavior in java?

All the other answers are technically correct, but IMHO if you implement a rough List of Lists of Lists you are not treating your data at the right level of abstraction. For example I am pretty sure that a List of Lists already means "something" in your business domain. Encapsulate this "something" in another object so you can just have a List<Something> instead of a difficult to use and maintain List<List<List<Object>>>.

As Mario says, you probably need to abstract out your data a little further. But, the following will do what you need.
In Java you would so something like:
List<List<List<Object>>> listOfListsOfLists =new ArrayList<List<List<Object>>>();
Then to access the items, you would use:
listOfListsOfLists.get(a).get(b).get(c);
Or, to iterate over everything:
for (List<List<Object>> list2: listOfListsOfLists) {
for (List<Object> list1: list2) {
for (Object o: list1) {
// use `o`
}
}
}

Since all of these answers make me barf, can I just add the suggestion that you either
Create a data type to express your data while encapsulating the details of the structure, or at least
Create a key type that wraps an int[] (but overrides equals and hashCode properly) and use a HashMap instead? It's typically rare that your whole 3-dimensional structure will be filled up much anyway.
Even better you could encapsulate that map and use varargs for clean access.
public class NDimensionalArray<V> {
private final int dimensions;
private final Map<Key, V> values = new HashMap<Key, V>();
private NDimensionalArray(int dimensions) {
this.dimensions = dimensions;
}
public V get(int... indices) {
checkIndices(indices);
return values.get(new Key(indices));
}
public void set(V value, int... indices) {
checkIndices(indices);
values.put(new Key(indices), value);
}
private void checkIndices(int[] indices) {
if ( indices.length != dimensions ) {
throw new IllegalArgumentException();
}
}
private static final class Key {
private final int[] indices;
private Key(int[] indices) {
this.indices = indices;
}
#Override
public int hashCode() {
return Arrays.hashCode(indices);
}
#Override
public boolean equals(Object obj) {
return Arrays.equals(indices, ((Key)obj).indices);
}
}
}
If people have examples of established collections libraries that already do this sort of thing, let me know and I'll add links.

While it is certainly true that you can construct a List<List<List<whatever>>> in Java, I can't help but wonder, Why do you want to do this? Not that it's inconceivable that this is the best solution to your problem, but wow, like why?
I guess I could imagine something like
public class Employee ...
List<Employee> store; // all the employees in a store
List<List<Employee>> city; // all the store lists for a city
List<List<List<Employee>>> nation; // all the store lists for the nation
But would you really want to process it that way? I don't know, it depends on what you need to do with it.

A comprehensive example showing List-of-List with collections and generics (Java 1.5+)
// declare the list of lists
List<List<String>> listOfListOfStrings = new ArrayList<List<String>>();
// populate
List<String> listOfStrings = new ArrayList<String>(); // one inner list
listOfStrings.add("one-one");
listOfStrings.add("one-two");
listOfListOfStrings.add(listOfStrings);
listOfStrings = new ArrayList<String>(); // and another one
listOfStrings.add("two-one");
listOfStrings.add("two-two");
listOfListOfStrings.add(listOfStrings);
// access
String oneOne = listOfListOfStrings.get(0).get(0); // first element of first inner list
String twoTwo = listOfListOfStrings.get(1).get(1); // second element of second inner list

Related

What's the data structure that works as an array but grows automatically into 2nd dimension when given multiple values under same index?

I remember this data structure which works based on indexes, as in an array or a list. However, if you put several values under the same index, that index turns into a linked list. Thus, upon adding new elements to that same index, the linked list would grow automatically.
I assume it is not just a 2D array. Also I heard it's possible to create an array of linked lists, but I still doubt that it is what I'm interested in.
Also, I assume that this is like some data structure from Java Collection because I remember seeing some code in Java containing this structure, but forgot its name.
Can some come up with some clues what may it be?
Or whether such data structure even exist?
Thanks
You can create your own data structure to implement the exact behavior you want.
One way to do this, is to use a HashMap of Integer as key and LinkedList as value.
Here is an example:
public class IndexMap {
Map<Integer, LinkedList<Integer>> map;
public IndexMap(){
map = new HashMap<Integer, LinkedList<Integer>>();
}
public void add(int index, int value) {
if(map.containsKey(index)) {
map.get(index).add(value);
}else {
LinkedList<Integer> list = new LinkedList<>();
list.add(value);
map.put(index, list);
}
}
public void remove(int index, int value) {
if(map.containsKey(index))
map.get(index).remove(new Integer(value));
}
#Override
public String toString() {
return map.toString();
}
public static void main(String[] args) {
IndexMap map = new IndexMap();
map.add(0,0);
map.add(0,1);
map.add(1,0);
map.add(2,0);
map.add(2,1);
System.out.println(map);
map.remove(0,1);
System.out.println(map);
}
}
Sample demo:
{0=[0, 1], 1=[0], 2=[0, 1]}
{0=[0], 1=[0], 2=[0, 1]}
You can alter the methods or add new ones to implement more functionalities.
You are probably thinking of a multimap. While there is no implementation in base java, there is one in google guava.
Here are introductions on how to use it in your build.

Comparing 2 lists and generating a new list with the differences

I am trying to build a function that compares 2 lists of objects and returns a list with differences.
I will use it to check if data retrieved from a crawler is new by comparing it with data from my database.
public static List checkForNewTweets(List timeline, List database) {
List<TimelineTweet> newTweets = new ArrayList<>();
List<TimelineTweet> timelineTweets = timeline;
List<TimelineTweet> databaseTweets = database;
for (TimelineTweet timelineTweet : timelineTweets) {
for (TimelineTweet databaseTweet : databaseTweets) {
if (!timelineTweet.equals(databaseTweet)) {
newTweets.add(timelineTweet);
break;
}
}
}
return newTweets;
}
This is not working at all, is there a way to make a recursive function for this?
Your current logic would probably add all the TimelineTweets to the newTweets list, since if databaseTweets contains at least two elements, at least one of them is not equal to a given element of the timelineTweets list.
Only after you finish comparing a timelineTweet to all the databaseTweets you can add it to the newTweets list (since that's the only way to know that the current timelineTweet doesn't match in any of the databaseTweets) :
for (TimelineTweet timelineTweet : timelineTweets) {
boolean found = false;
for (TimelineTweet databaseTweet : databaseTweets) {
if (timelineTweet.equals(databaseTweet)) {
found = true;
break;
}
}
if (!found)
newTweets.add(timelineTweet);
}
looking at your code I think only only want to remove the elements of the second list from the first and assign it to a third.
why dont you use timeline.removeAll(database) and then newTweets.addAll(timeline)
Consider another approach.
public static <E> List<E> getDiff(List<E> list, List<E> list1){
if(list.size() >= list1.size())
return getDiffList(list, list1);
return getDiffList(list1, list);
}
private static <E> List<E> getDiffList(List<E> list, List<E> list1) {
List<E> newList = new ArrayList<>(list);
newList.removeAll(list1);
return newList;
}
Please note this will report just different elements and any duplicates will be ignored.
List<String> strings = Arrays.<String>asList("A", "B", "C");
List<String> strings1 = Arrays.<String>asList("A","B","D","C","B","Z","A");
Result list will be [D, Z]
In case this is an option, you should have a look at the the Set classes of java, since containment is much cheaper to compute for those classes. I guess your TimelineTweets are Comparable eg wrt their timestamp, thus can be used in a TreeSet, that allows lookup and insertion in log(n). A different option would be LinkedHashSet providing insertion order iteration and constant time operations or just HashSet if you dont care about ordering at all.
If you don't need the timeline again but are only interested in the new tweets, you can just remove all the items already in the database:
public static TreeSet<TimelineTweet> checkForNewTweets(
final TreeSet<TimelineTweet> timeline, final TreeSet<TimelineTweet> database) {
timeline.removeAll(database);
return timeline;
}
Alternative: copy the timeline, afterwards remove the database entries.
public static TreeSet<TimelineTweet> checkForNewTweets(
TreeSet<TimelineTweet> timeline, TreeSet<TimelineTweet> database) {
final TreeSet<TimelineTweet> newTweets = new TreeSet<>(timeline);
newTweets.removeAll(database);
return timeline;
}
The operations are available for all collection classes in Java, but are faster for Sets.

Comparing lists of different types

I have two lists as follows
List<MyObject1> list1
List<Long> list2
The list2 is basically the list of Id's of MyObject1 which is a property in the object
Public Class MyObject1 implements Serializable{
private Long myObjId;
.....
.....
//other elements go here
public Long getMyObjId() {
return myObjId;
}
public void setMyObjId(Long myObjId) {
this.myObjId = myObjId;
}
I want to compare the two lists to check if all the objects in list1 are contained in list2
One way is to iterate over the list1, create a new list of Id's out of it and then use the containsAll method on it.
Is there a simpler way to achieve the same result?
In Java 8 you can write what you described: "One way is to iterate over the list1, create a new list of Id's out of it and then use the containsAll method on it." in one line as:
list1.stream().map(a -> a.getMyObjId()).collect(Collectors.toList()).containsAll(list2);
map converts a each MyObeject to an id by calling a.getMyObjectId and collect creates a list
as a result.
There are at least two conceptually different approaches:
One could collect the IDs in a list, and work on the resulting list
One could do the check on-the-fly
The first one would boil down to something like
boolean allIdsContained(List<MyObject> myObjects, List<Long> validIds) {
List<Long> ids = new ArrayList<Integer>();
for (MyObject m : myObjects) ids.add(m.getID());
return validIds.continsAll(ids);
}
The second one could be written as
boolean allIdsContained(List<MyObject> myObjects, List<Long> validIds) {
for (MyObject m : myObjects) {
if (!validIds.contains(m.getID()) {
return false;
}
}
return true;
}
Note that the method signature is the same in both cases, so you are free to change the implementation according to your needs. Particularly, if the list if validIds is large, then it could be more efficient to first convert it to a Set. (The contains method on a List is O(n), whereas on a Set, it is O(1)). Then the method could be implemented as
boolean allIdsContained(List<MyObject> myObjects, List<Long> validIds) {
Set<Long> set = new HashSet<Long>(validIds);
for (MyObject m : myObjects) {
if (!set.contains(m.getID()) {
return false;
}
}
return true;
}
In any case, all these methods could be written more concisely with Java 8 Lambdas, but I think that this should be an implementation detail, and should be hidden in such a helper method regardless of how it is implemented.

How to implement the getter/setter for a Collection field in a Java class?

I'm creating a JavaBean that contains a List and can think of two possibilities:
public class JavaBeanWithSettableList {
private List<Integer> list;
public List<Integer> getList {
return list;
}
public void setList(final List<Integer> list) {
this.list = list;
}
}
...or...
public class JavaBeanWithUnsettableList {
private List<Integer> list = new ArrayList<Integer>();
public List<Integer> getList {
return this.list;
}
// No setter - need to use list.add(), list.remove() etc.
}
The second one I've seen used on another project - it seems better but I'm not sure where this design came from. Could anyone point me towards an article naming the pattern and/or describing its benefits?
There is no name for this pattern. The first one is just a class with a List and the second one is a list which is created internally.
Generally the less state and the more immutability you have in your classes are the better. The reason for this is that if you have less state you have less chance of producing an error.
In your case if for example you use the first approach then you can't make sure that someone else does not set another list to your model. In the second case you can't make sure that someone will not call clear() on your list.
In the end it all depends on your use case. If you want your class to hold a list but you don't want any changes in the future you should use an immutable list. Otherwise restrict the mutability as much as you can.
Neither will be optimal. Roughly you want...
public class ModelList {
private List<Integer> list;
ModelList() {
this.list = new ArrayList<Integer>();
}
ModelList(final List<Integer> list) {
this.list = list;
}
public ArrayList<Integer> getList {
return new ArrayList<Integer>(list); // Send back a copy, to make Immutable
}
}
The problem with the first one is that everytime you want to update your list, you need to create a new list, get the list from your model, add your element and set the new list to your model.
The second one allow you to do it without the need to get the list and reset it after !

How to return the correct type of list?

If I have a method like this (for simplicity assume integers):
public static List<Integer> doSomething(List<Integer> list) {
// logic here
}
and I need for my processing to create internally a new list which I will create and somehow populate and return to the caller, how can I do it since I don't know what type of list the caller passed in?
I don't want to return a List of different type that what the caller passed in.
E.g. If the caller passed a LinkedList and I don't want to return an ArrayList.
How can this issue best be approached?
You shouldn't tie your implementation to a particular implementation of List, the idea of using an interface is that, from the outside, it shouldn't matter what concrete class you're instantiating as long as it conforms to the List interface.
EDIT :
Anyway, here's a possible way:
List<Integer> lst1 = new ArrayList<Integer>();
Class<?> klass1 = lst1.getClass();
List<Integer> copy1 = (List<Integer>) klass1.newInstance();
System.out.println(copy1.getClass().getName());
> java.util.ArrayList
List<Integer> lst2 = new LinkedList<Integer>();
Class<?> klass2 = lst2.getClass();
List<Integer> copy2 = (List<Integer>) klass2.newInstance();
System.out.println(copy2.getClass().getName());
> java.util.LinkedList
As you can see in the console, the copies are instances of the same class as the original list.
If you can get away with just using one of those two output types, then you can do
if (inputList instanceof RandomAccess) {
// use an ArrayList
} else {
// use a LinkedList.
}
The RandomAccess interface is meant to indicate that the implementation allows O(1) get operations.
Marker interface used by List implementations to indicate that they support fast (generally constant time) random access. The primary purpose of this interface is to allow generic algorithms to alter their behavior to provide good performance when applied to either random or sequential access lists.
By doing this, your APIs allow clients to defend their inputs. They can pass in the result of Collections.unmodifiableList(...) and be sure that it isn't modified by other code.
If you really know the input is a mutable list, you can clone() the list, then clear() it. Both ArrayList and LinkedList have public clone() methods which can be accessed reflectively.
The best thing to do is to remove the list creation from the method. Have the caller decide how to create the list:
public static void doSomething(List<Integer> dest, List<Integer> src) {
You could use Class.newInstance to create a list of the passed in type:
public static List<Integer> doSomething(List<Integer> list)
{
List<Integer> newList = null;
try
{
newList = list.getClass().newInstance();
}
catch(InstantiationException e)
{
throw new RuntimeException(e);
}
catch(IllegalAccessException e)
{
throw new RuntimeException(e);
}
//Logic here
return newList;
}
#Test
public void test()
{
List<Integer> testList = new ArrayList<Integer>();
List<Integer> resultList = doSomething(testList);
Assert.assertEquals(testList.getClass(), resultList.getClass());
Assert.assertNotSame(LinkedList.class, resultList.getClass());
testList = new LinkedList<Integer>();
resultList = doSomething(testList);
Assert.assertEquals(testList.getClass(), resultList.getClass());
Assert.assertNotSame(ArrayList.class, resultList.getClass());
}
If you really, really care what kind of object comes out, I would include that as a parameter to the method, like:
<T extends List<Integer>> T doSomething(Class<T> returnType,List<Integer> v)
throws Exception
{
// constructors for your return will be tricky :)
// returnType.newInstance() will probably work.
T result = returnType.newInstance();
result.add(86); result.add(99);
return result;
}

Categories

Resources