Combining lists into an arraylist (C#) - list

I have a list and I want to copy three other lists into it.
// The main list
List<List<string>> list= new List<List<string>>();
// The lists which I want to combine
ArrayList sublist1= new ArrayList();;
ArrayList sublist2= new ArrayList();;
ArrayList sublist3= new ArrayList();;
What I tried is:
list[0].AddRange(sublist1);
list[0].AddRange(sublist2);
list[0].AddRange(sublist3);
It doesn't work because It is multidimensional list. I need this type of list for the future plans.
How can I accomplist it?

As already mentioned in comments just use List<string> instead of ArrayList.
It has nothing to do about multidimensional arrays, just types mismatch.
Then you say List<List<string>> it basically means create list type, which will contain List<string> as items (the part in angle brackets), so you need to add them, not ArrayLists. Similarly List<string> means type of list which will contain string as items.

As in the comments, you need to pass a type that follows IEnumerable. For example, you can change your ArrayLists to List
// The main list
List<List<string>> list = new List<List<string>>();
// The lists which I want to combine
var sublist1 = new List<string>();
var sublist2 = new List<string>();
var sublist3 = new List<string>();
list[0].AddRange(sublist1);
list[0].AddRange(sublist2);
list[0].AddRange(sublist3);

change type of sublists to some IEnumerable<string> (string[] or List<string> or something else)
var sublist1 = new string[] {};
var sublist2 = new string[] {};
var sublist3 = new string[] {};
OR do cast
list[0].AddRange((IEnumerable<string>) sublist1);
list[0].AddRange((IEnumerable<string>) sublist2);
list[0].AddRange((IEnumerable<string>) sublist3);
Because you are trying to use AddRange method of System.Collections.Generic.List<T>
and the signature of this method is
public void AddRange(System.Collections.Generic.IEnumerable<T> collection)
so it requires IEnumerable as a parameter.

Related

Why an instance of List<> influences Instance of an ArrayList<>?

I was testing this code in java and was wondering, why manipulating Instance List2 affects Instance List1?
As both prints print the same list including "Kiwi"
Is that because List2 is a List reference while list1 is an ArrayList Class instance?
import java.util.ArrayList;
import java.util.List;
public static void main(String[] args) {
ArrayList<String> List1 = new ArrayList<String>();
List1.add("Apple");
List1.add("Banana");
List1.add("Orange");
List<String> List2 = List1;
List2.add("Kiwi");
System.out.printf("List1 =%s\n", List1);
System.out.printf("List2 =%s\n", List2);
}
}
It would be great to get an explanation,
thanks!
After this line...
List<String> List2 = List1;
... you have two variables pointing to the same ArrayList object.
Copying objects like lists is not trivial in Java. The next step for you might be:
List<String> List2 = new ArrayList<>(List1)
(btw... you shouldn't capitalize your variable names)
That will behave more according to you expectations, I think. If you define List2 that way, only List2 will get "Kiwi" added to it. List1 will remain as it was ("Apple", "Banana", "Orange").
This is actually all you need, since you are putting String objects in your lists, and Strings are immutable in Java.
However, suppose you did something like:
ArrayList<MyComplexObject> list1 = new ArrayList<>();
list1.add(new MyComplexObject());
list1.add(new MyComplexObject());
list1.add(new MyComplexObject());
ArrayList<MyComplexObject> list2 = new ArrayList<>(list1);
... you will have two separate lists. If you remove an element from list2, it will still be in list1. However, if you modify an element in list2, it will also be modified in list1. This is because, while the lists are separate objects, each one is pointing to the same instances of MyComplexObject.
If that behavior is not what you need, you need to do a "deep copy" of the List, which can be involved.

how to pass all List<String> native methods to a List<Random>?

I'm new in Flutter(Dart) and I came across this problem. All lists of the type String naturally have the string methods like item.length, item.contains and so on. But when you create a random List type, it gets none of that. What is the recommended way of inherit all List properties to the custom one?
You probably didn't provide a list type and you can't see String methods.
void main() {
List<String> names = ['Dave', 'Ana', 'Robert'];
names.shuffle();
for(var name in names) {
print('name: $name, lenght: ${name.length}');
}
}

Cannot add elements into the List Salesforce

Please tell me why I cannot add these elements into the List. Please find the attached screenshot for the error.
public class PracticeOnLists {
List<String> myList = new List<String>();
myList.add('element1');
myList.add('element2');
myList.add('element3');
myList.add('element4');
System.debug('The List is' + myList);
System.debug('The size o the List is ' + myList.size());
}
There are major problems in your code.
List is an interface, so you cannot create objects of an interface. You'll have to create an object from a child class of List.
In Java you need double quotes(") to create a String.
And you cannot write statements just inside a class. They must be in a method or a block.
If you want to get viewable outputs I suggest you use System.out.println() since there's no method called debug() in the System class.
So this should be your code
List<String> myList = new ArrayList<String>();
void addToList() {
myList.add("element1");
myList.add("element2");
myList.add("element3");
myList.add("element4");
System.out.println("The List is" + myList);
System.out.println("The size o the List is " + myList.size());
}
The problem is that you have to do this inside a method. Single quotes are correct-double quotes are wrong in Apex(Salesforce) NOT Java.
public void doItHere() {
myList.add('element1');
myList.add('element2');
myList.add('element3');
myList.add('element4');
}

convert TreeMap<String,Object> to List<HashMap<String,Object>>

I have a TreeMap<String,Object> which contains Objects that are actually HashMap<String,Object>. I want to convert this to List<HashMap<String,Object>>. I was trying to convert it using Java 8 and wrote the following code which is giving compilation error due to conversion from List<Object> to List<HashMap<String,Object>>.
public static void main(String[] args) {
TreeMap<String,Object> treeMap = new TreeMap<String,Object>();
HashMap<String,Object> map1 = new HashMap<String,Object>();
map1.put("a",1);
map1.put("b","2");
map1.put("c",5);
treeMap.put("01",map1);
HashMap<String,Object> map2 = new HashMap<String,Object>();
map2.put("a",5);
map2.put("b","7");
map2.put("c",6);
treeMap.put("02",map2);
//this conversion is not working as Java is not allowing to convert from List<Object> to List<HashMap<String,Object>>
List<HashMap<String,Object>> list= treeMap.values().stream()
.collect(Collectors.toList());
}
Changing the TreeMap to TreeMap<String,HashMap<String,Object>> works but I don't want to make this change as I am passing this to a separate method which expects TreeMap<String,Object>.
Please suggest.
Well, you define the treeMap to have Object values, this is why values().stream() returns a Stream<Object>. Either change your contract or you'll need to cast the elements in the stream:
List<HashMap<String,Object>> list= treeMap.values().stream()
.map(element -> (HashMap<String,Object>)element)
.collect(Collectors.toList());
I would start by giving treeMap the proper types: TreeMap<String, HashMap<String, Object>>.
You can then wrap the map and pass new TreeMap<String, Object>(treeMap) to that other method.
Nicer, as it does not require a new map, would be to follow Sean's comment and change that method's parameter from TreeMap<String, Object> to TreeMap<String, ?>, if you are allowed to do that.

Dropwizard /Jersey: Pass query-parameter with multiple values as List (maybe using a filter)

I have clients passing in IDs like this: /v1/path?id=1,2,3
What I have and want
I have a resource class for Dropwizard/Jersey.
I'd like to show up the query-parameter id=1,2,3 as a List parameter in my resource's GET method
// Resource class
public List<Something> getFilteredList(#QueryParam("id") List<String> ids) {
// filter the List<Something> based on a list of ids
}
Right now, the ids list contains 1 string which is "1,2,3".
What I tried
I tried a filter but the query parameters given by Jersey's
ContainerRequestContext.getUriInfo().getQueryParameters()
is immutable.
Questions
I would like to apply a filter and change any comma separated query parameters into multi-valued parameters so that the resource method gets a list instead.
Is there a way to change the existing query parameters using a Jersey filter?
What's a good way to solve this problem?
The best way I can think of is to just create a wrapper class for the list. This makes it easier to take advantage of the specified functionality of Jersey. You can see what I mean at Passing custom type query parameter.
For example
public class IdFilter {
private List<String> ids = new ArrayList<>();
public List<String> getIds() { return ids; }
public static IdFilter valueOf(String param) {
IdFilter filter = new IdFilter();
for (String id: param.split(",") {
filter.getIds().add(id);
}
}
}
getFilteredList(#QueryParam("id") IdFilter ids) {
We don't need to do anything else. Just having the static valueOf is enough for Jersey to know how to parse the query string.
3 ways to solve it:
use the generic context-parameter UriInfo , which is not very expressive
add an explicit custom type that can parse a comma-separated list
stay with #QueryParam List<String> requiring a concatenated query like ?id=1&id=2&id=3 given as URI
I would prefer the second as most-expressive, like answered already by Paul. This way you can concisely pass a single CSV like ?id=1,2,3,3 and also use a Set to ensure unique ID values, e.g. resulting in only [1, 2, 3].
Generic context-param UriInfo
One way would be to use a generic parameter #Context UriInfo to get the list in the method's body:
public List<Something> getFilteredList( #Context UriInfo uriInfo ) {
List<String> idList = uriInfo.getQueryParameters().get("id"); // before was #QueryParam("id")
System.out.println("idList: " + idList);
// filter a given list by ids
var somethingFiltered = getSomethingList().stream()
.filter(s -> idList.contains(s.getId()))
.collect(toList());
return Response.status(Status.OK).entity(somethingFiltered).build();
}
See the tutorial in Java Vogue(2015): QueryParam Annotation In Jersey -
Custom type with static valueOf(String) factory-method
The other way is to design a custom type which can be constructed using a String:
class IdSet {
Set<String> values;
// a factory method, can also be named valueOf
public static IdSet fromString(String commaSeparated) {
return new HashSet( Arrays.asList( commaSeparated.split(",") ) );
}
}
public List<Something> getFilteredList(#QueryParam("id") IdSet ids) {
System.out.println("ids (Set): " + ids.values);
// filter a given list by ids
var somethingFiltered = getSomethingList().stream()
.filter(s -> ids.values.contains(s.getId()))
.collect(toList());
return Response.status(Status.OK).entity(somethingFiltered).build();
}
See Jersey's JavaDocs for #QueryParam:
The type T of the annotated parameter, field or property must either:
Be a primitive type
Have a constructor that accepts a single String argument
Have a static method named valueOf or fromString that accepts a single String argument (see, for example, Integer.valueOf(String))
Have a registered implementation of ParamConverterProvider that returns a ParamConverter instance capable of a "from string" conversion for the type.
Be List<T>, Set<T> or SortedSet<T>, where T satisfies 2, 3 or 4 above. The resulting collection is read-only.
Use a collection interface with multiple key-value pairs
When the calling client uses following URI pattern: /something?id=1&id=2&id=3 then JAX-RS can deserialize them to a single parameter of List<String> id having given multiple elements:
public List<Something> getFilteredList(#QueryParam("id") List<String> ids) {
System.out.println("ids : "+ids);
// filter a given list by ids
var somethingFiltered = getSomethingList().stream()
.filter(s -> ids.contains(s.getId()))
.collect(toList());
return Response.status(Status.OK).entity(somethingFiltered).build();
}
See Mkyong: JAX-RS #QueryParam example where explained the multiple occurrences of orderBy in the GET query:
#QueryParam will convert the query parameter “orderBy=age&orderBy=name” into java.util.List automatically.
See also
Handling Multiple Query Parameters in Jersey
Deserializing List<Map<String, String>> QueryParam in jersey 1
Jersey, #QueryParam List<String>