How iterate an ArrayList inside various others ArrayLists? - java

I was notified that is possible to create "infinite" ArrayLists inside others, such as in the code below:
import java.util.ArrayList;
public class Main
{
public static void main(String[] args) {
ArrayList<ArrayList<ArrayList<ArrayList<ArrayList<Object>>>>> List = new ArrayList<ArrayList<ArrayList<ArrayList<ArrayList<Object>>>>>();
}
}
And I want know about how to iterate them (with foreach or other loop types)

You could try to traverse it like a composite:
public static void traverse(ArrayList<T> arg) {
arg.forEach(
(n) -> if (n instanceof ArrayList) {
traverse(n)
} else {
doStomething(n)
}
);
}

IMHO, if someone writes such structures - it's some kind of a maniac.
But still, you can follow this kind of pattern in order to traverse:
#Test
public void test4() {
List<String> list1 = new ArrayList<>();
list1.add("abc");
list1.add("def");
List<List<String>> list2 = new ArrayList<>();
list2.add(list1);
list2.stream().flatMap(Collection::stream).forEach(System.out::println);
}
```

Related

Add values from basic array to Set<String>

private Set<String> fields = new HashSet<>();
public void fields(String... s){
this.fields.addAll(s);
}
Doesn't compile, saying that:
addAll
(java.util.Collection<? extends java.lang.String>)
in Set cannot be applied
to
(java.lang.String[])
is there is a good way to get around this?
I think you can convert your array to a list first. Maybe something like
this.fields.addAll(Arrays.asList(s));
If you further don't want to modify the Set, you can use Set.of with Java-9+ as:
public void fields(String... s) {
this.fields = Set.of(s);
}
or else you can use Collections.addAll as in:
public void fields(String... s) {
Collections.addAll(fields, s);
}
You simply convert array to Set as below code.
String [] array = new String[] {"one","two","three","four","five"};
Set<String> set = new HashSet<String>(Arrays.asList(array));
If you can use google Guava the follow code may help you
public void fields(String... s) {
this.fields.addAll(Sets.newHashSet(s));
}
another method:
public void fields1(String... s) {
Sets.union(fields,Sets.newHashSet(s)).copyInto(fields);
}

Java: For loop on Objects of Strings

I'm new in Java and I have to solve this exercise. I have this code:
public class StringList {
private String list = "";
public StringList(String... str) {
for (String s : str) list += s+"\t";
}
}
and I have to change the class so that its objects allow the iteration by using this instruction:
for (String s : new StringList("a", "b", "c")) System.out.println(s);
My idea was to create a List and iterate on it. So I changed the code in this way:
public class StringList {
private List<String> list = new ArrayList<String>();
public StringList(String... str) {
for (String s: str) list.add(s);
}
}
but when I try the iteration with the above instruction I get this error (Can only iterate over an array or an instance of java.lang.Iterable) and I spent hours trying to fix it but I keep failing. Any help?
To do it the clean way, give a look at the java.lang.Iterable interface : https://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html
If your StringList class implements it, then the instruction will work. I'll let you complete the exercise yourself though, but you can start with
public class StringList implements Iterable<String> {
// the attribute you need to store the strings object
// your constructor
#Override
public Iterator<String> iterator() {
// This is what you need to fill
}
}
PS : Using a list of string as an attribute is not a bad idea at all and will save you a lot of efforts and time, search what you can do with it
You have to implement Iterable<String> to your StringList like this:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Spliterator;
import java.util.function.Consumer;
public class StringList implements Iterable<String> {
private List<String> list = new ArrayList<String>();
public StringList(String... str) {
for (String s: str) { list.add(s); }
}
#Override
public Iterator<String> iterator() {
return list.iterator();
}
#Override
public void forEach(Consumer<? super String> action) {
list.forEach(action);
}
#Override
public Spliterator<String> spliterator() {
return list.spliterator();
}
}

use Streams to generate a new list taking into account all the first list elements

I would like to map a list to another one. The decision is to be made on all the elements of the first list. Here is how it would look like, in crappy code :
import java.lang.Math;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
public class HelloWorld
{
public static void main(String[] args)
{
MatchingClass myObject = new MatchingClass();
System.out.println(myObject.getMatchingEnums(Arrays.asList("param1", "param3", "param2")));
System.out.print(myObject.getMatchingEnums(Arrays.asList("param1", "param3", "param4")));
}
}
enum TheEnums {
elem1("param1", "param2"),
elem2("param1", "param3");
String[] parameters;
TheEnums (String... parameters){
this.parameters = parameters;
}
String[] getParams (){
return parameters;
}
}
// you can add other public classes to this editor in any order
public class MatchingClass
{
public List<TheEnums> getMatchingEnums (List<String> givenParameters) {
List<TheEnums> result = new ArrayList<>();
for (TheEnums theEnum : TheEnums.values()){
if (givenParameters.containsAll(Arrays.asList(theEnum.getParams()))){
result.add (theEnum);
}
}
return result;
}
}
This could be written better, but what I want to know is if we can use the Java 8 Stream to be able to do that.
Maybe using Collectors ?
Thanks.
For example:
class MatchingClass {
public List<TheEnums> getMatchingEnums(List<String> givenParameters) {
List<TheEnums> enumsList = Arrays.asList(TheEnums.values());
return enumsList.stream()
.filter(e -> givenParameters.containsAll(Arrays.asList(e.getParams())))
.collect(Collectors.toList());
}
}

transform Collection<myClass> to Collection<String>

I trying to implement functionally similar to CollectionUtils transform (Apache Commons Collections)
class CollectionUtils {
public static void transformerModifier(Collection<MyClass> myCollection) {
// How should I implement this method in order that
// output from the line 1 and line 2 will be the same ?
}
public static List<String> transform(Collection<MyClass> myCollection) {
List<String> strCollection = new LinkedList<>();
for (MyClass item : myCollection) {
strCollection.add(item.getName());
}
return strCollection;
}
}
class myClass {
private String name;
private int value;
myClass( String name, int value) {
this.name = name ;
this.value = value;
}
public String toString(){
return new String(name+ ":" + value ) ;
}
}
class MyClassCollection{
private List<myClass> list ;
myClassCollection(List<myClass> list){
this.list = list;
}
List<myClass> collection(){
return list.clone();
}
}
public class TestClass{
public static void main (String[] args) {
List<MyClass> list = new ArrayList<>();
list.add(new myClass("John", 12);
list.add(new myClass("Mike", 16);
list.add(new myClass("Eric", 13);
list.add(new myClass("Mark", 142);
list.add(new myClass("Alex", 112);
MyClassCollection myOjb = new MyClassCollection(list );
CollectionUtils.transformerModifier(myObj.collection() );
List<MyClass> myList = CollectionUtils.transform(myObj.collection());
System.out.println(Arrays.toString(myObj.collection().toArray)); // line 1
System.out.println(Arrays.toString(myList.toArray)); // line 2
}
}
output: [John,Mike,Eric,Mark,Alex] // output after line 1
output: [John,Mike,Eric,Mark,Alex] // should be output after line 2
My question is it possible to implement method transformerModifier in the way that it will change collection of the object myObj so that myObj.collection() return not the List<myClass> but the List of List<String> ( where string is the data from private String name data member of myClass ) ?
My guess is that the solution should be through anonymous class. However, I didn't understand yet how should I implement it.
If you are using Java 8, you could make use of streams and map() to do something like this:
List<MyClass> myClassList = new ArrayList<>();
//add your items to myClassList here
List<String> names = myClassList.stream().map(MyClass::getName).collect(Collectors.toList());
//names will now consist of a List of all the names associated with
//each of the MyClass objects within myClassList in the same order
This solution makes use of Method Reference as well MyClass::getName. This calls the getName method on each object in the stream mapping it to its respective spot in the transformed stream using .map().
Next it uses .collect() to bring it back from a stream to a list using Collectors.toList().
If you are working with a lot of objects within myClassList, this process can be sped up using .parallelStream() instead of .stream(), but if you are not working with a large amount of data, you may see a reduction in performance with .parallelStream(). It all depends on how many objects you expect to be present within the List.
public interface Converter<I, O> {
void tranformer(List list);
O retriever(I obj);
}
_
public static <I, O> void transform(Converter<I, O> converter, List inputList) {
Iterator<I> it = inputList.iterator();
List list = new LinkedList<>();
while (it.hasNext()) {
list.add(converter.retriever(it.next()));
}
converter.tranformer(list);
}
_
public static void main(String[] args) {
List<MyClass> list = new ArrayList<>();
list.add(new myClass("John", 12);
list.add(new myClass("Mike", 16);
list.add(new myClass("Eric", 13);
list.add(new myClass("Mark", 142);
list.add(new myClass("Alex", 112);
MyClassCollection myclasscollection = new MyClassCollection(list);
final List collectionList = myclasscollection.collection();
CollectionUtils.transform(new Converter<myClass, String>() {
#Override
public void tranformer(List list) {
employeeList.clear();
employeeList.addAll(list);
}
#Override
public String retriever(myClass obj) {
return obj.name; // make the data member public or add getter
}
}, collectionList);
collectionList.get(0).toString.toLowerCase();
}
This isn't fully what you need but I bet this isn't bad alternative. Please, notice that could output collection collectionList will be collection of objects ( not String ), however, you can access to methods of the String data type just to right like this collectionList.get(0).toString.toLowerCase(); Hope this help.

Need to loop over an array/list/whatever and *return to caller* each element -but the loop only runs once, of course

I'm obviously missing something here, as this sound basic enough but yet...
I have a collection of objects . I need to use each one of them as parameter in constructor for a new object and return each new object to the caller method, one by one.
But -if I loop over the collection obviously the loop only runs once, and only returns the 1st object.
Edit : Returning the whole collection or some new collection will not work because :
The caller method [not mine to change] runs inside a start() method of a Runnable ThingProvider, which returns a single Thing whenever a request is submitted to it. So, returning List is not possible.
Thanks :)
public List<T> loop(Collection<? extends U> coll) {
List<T> a = new ArrayList<T>();
for (U u : coll){
a.add(new T(u));
}
return a;
}
Return a custom Iterator. Assumming your new objects are of class MyObject and the constructor accepts an Object:
public Iterator<MyObject> myObjectsIterator(final Iterator<? extends Object> it) {
return new Iterator<MyObject>() {
public boolean hasNext() {
return it.hasNext();
}
public MyObject next() {
return new MyObject(it.next());
}
public void remove() {
it.remove();
}
};
}
And you would call it like this:
...
Iterator<MyObject> myIt = myObjectsIterator(myListOfObjects.iterator());
// Now you can pass myIt around as a normal object. It will remember
// which one is the next Object with which to construct a MyObject
// and will generate it on the fly
...
while (myIt.hasNext()) { // is there any MyObject remaining?
MyObject myObj = myIt.next(); // gets the next MyObject
// do something with myObj
}
...
This is a poorly worded question and I think as others have noted, just returning a new list of the objects is fine. But if you really want to process them one at a time while you're looping through it, you can use the command pattern.
public interface Command {
void execute(NewType object);
}
Now in your caller method, you can do the following:
public void doSomething() {
processList(myList, new Command() {
void execute(NewType object) {
// Do whatever you want with this object
}
});
}
And, in the method that will actually go through the list:
public void processList(Iterable<OldType> values, Command command) {
for(OldType v : values) {
NewType newType = new NewType(v);
command.execute(newType);
}
}
In java you can return only once. So if you want to get some informations from your methods either you wrap them into a "Big" Object (here a List) or you give to the method the means to put informations in your parameters.
You could have something like this :
public static void main(String... args){
List<Parameter> parameters = methodToGetParameters();
List<Result> results = generateObjectsFromList(parameters);
for(Result result : results){
handleAResult(result);
}
}
public List<Result> generateObjectsFromList(List<Parameter> parameters){
List<Result> results = new ArrayList<Result>();
for(Parameter parameter : parameters){
results.add(new Result(parameter));
}
return results;
}
Or like this :
public static void main(String... args){
List<Parameter> parameters = methodToGetParameters();
List<Result> results = new ArrayList<Result>();
generateObjectsFromList(parameters, results);
for(Result result : results){
handleAResult(result);
}
}
public void generateObjectsFromList(List<Parameter> parameters, List<Result> results){
for(Parameter parameter : parameters){
results.add(new Result(parameter));
}
}
A third way to do this would be to use fields, but it's not really good to have a lot of fields if they're not really used (or only by one method).
On the same topic :
Java Object Oriented Design Question: Returning multiple objects in java(Updated)
Using a java method to return multiple values?
Return a collection from the method and in the collection implement a custom iterator to transform the input collection to the new collection. The following code shows how to do it using the Google Guava library:
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
public class Test {
static class Person {
public final String name;
public Person(String name) {
this.name = name;
}
}
public static Collection<Person> peopleFromNames(Collection<String> names) {
return Collections2.transform(names, new Function<String, Person>() {
public Person apply(String name) {
return new Person(name);
}});
}
public static void main(String[] args) {
List<String> names = Arrays.asList("Brian", "Albert", "Roger");
for (Person person : peopleFromNames(names)) {
System.out.println(person.name);
}
}
}
do you mean using of delegates something like below
public class Test {
private static class Person{
private final String name;
Person(String name){
this.name = name;
}
#Override
public String toString() {
return return name;
}
}
private interface Printer {
void print(Object object);
}
public static void main(String[] args) {
final String[] names = {"one", "two", "three"};
final ArrayList<Person> people = construct(names, new Printer() {
#Override
public void print(Object object) {
System.out.println(object.toString());
}
});
}
private static ArrayList<Person> construct(String[] names, Printer printer) {
ArrayList<Person> people = new ArrayList<Person>();
for (String name : names) {
printer.print(new Person(name));
}
return people;
}
}
It's Possible.
Check these Project for Java-yield , yield4Java, infomancers
If you're using this just once in your entire code, You're better off choosing a method from the other answers.
Return a list of the new objects.

Categories