MultiMap in Flutter - flutter

I would like to have a multimap or ListMultiMap in flutter, since I require multiple values with same key, when I use dart's quiver collection as per the dart document, MultiMap showing error, saying no such method. Can anyone help me please.
imported quiver collection and then tried using Multimap class
import 'package:quiver/collection.dart';
https://pub.dev/documentation/quiver/latest/quiver.collection/Multimap-class.html
tried using Multimap as per above documentation, but showing error
Multimap<String, String> multimap = new MultiMap<String,String>();

You might have a typo. Note that you are saying new MultiMap with the M of map capitalized. (Note that the new keyword isn't needed and should be dropped.)
The following works as expected:
import 'package:quiver/collection.dart';
void main() {
var myMap = Multimap<String, String>();
myMap.add('a', 'a1');
myMap.add('a', 'a2');
myMap.forEach((key, value) => print('[$key->$value]'));
}
and prints:
[a->a1]
[a->a2]

Related

Dart encapsulated list (just for observing values)

I have the following lists
List<ProductVariation> _productVariations = []; avoid null pointer exceptions
List<ProductVariation> get productVariations => _productVariations;
The main goal for adding List<ProductVariation> get productVariations => _productVariations; was to avoid _productVariations to be modified, however, I'm able to add, delete or do any operations inside the list, how can I prevent productVariations to be modified when accessed from another file?
An alternative solution is to use UnmodifiableListView from dart:collection which can be a lot more efficient since you are not making a new copy of the list but are instead just serving a protected view of your List:
import 'dart:collection';
class A {
final List<int> _data = [1, 2, 3];
UnmodifiableListView<int> get data => UnmodifiableListView(_data);
}
void main() {
final a = A();
print(a.data); // [1, 2, 3]
a.data.add(5); // Unhandled exception: Unsupported operation: Cannot add to an unmodifiable list
}
A downside of this solution is that UnmodifiableListView is a normal List seen from the analyzers point of view so you will not get any statically errors from doing this. But you will get an exception on runtime if you try modify the list itself. For making it more clear for the developer I think it is nice to specify that the returned type is UnmodifiableListView even if you could just write List instead.
Another point is that this solution (or the one suggested by Jigar Patel) does not prevents you from modifying the objects itself in the list if the objects are not immutable. So if you also want to prevent these changes you need to make deep copies of the objects.
You can make the getter return a copy of the list like this.
List<ProductVariation> get productVariations => [..._productVariations];
Or
List<ProductVariation> get productVariations => _productVariations.toList();

Iterate over _InternalLinkedHashMap not working

I'm trying to iterate over the following data structure: {String: [{String, List<SomethingResponse>}]} where SomethingResponse = {String: dynamic}). I created this model:
class SomethingsResponse {
final Map<String, List<SomethingResponse>> SomethingsResponse;
SomethingsResponse({this.SomethingsResponse});
factory SomethingsResponse.fromJson(data) {
return SomethingsResponse(SomethingsResponse: data.map<String, List<SomethingResponse>>((String key, dynamic value) {
final dataFromCategory = List<SomethingResponse>.from(value.map((x) => SomethingResponse.fromJson(x)));
return MapEntry(key, dataFromCategory);
}));
}
}
When I try getting the keys like this: data.somethingsResponse.toList(), I get an error saying:
Class '_InternalLinkedHashMap<String, List>' has no instance method 'toList'.
I can't iterate over it or really get any kind of data out of it. What am I doing wrong and how can I fix it? I have a feeling the issue is at this line return MapEntry(key, dataFromCategory);, but I tried creating a Map a couple of different ways, and none worked.
If you consult the documentation for Map, you will see that it does not derive from Iterable and therefore cannot be directly iterated over. I presume that this is because it's not obvious what you want to iterate over: keys, values, or key-value pairs?
If you want to iterate over keys, use Map.keys. (In your case: data.somethingsResponse.keys.toList())
If you want to iterate over values, use Map.values.
If you want to iterate over key-value pairs (i.e. MapEntry objects), use Map.entries.

Is Map of lists not possible in dart?

I have data in this order :-
m={ 1:[54,23,98],
9:[8,4,2]
}
I'm trying to achieve something like this using the following code but it's not working. Where am I going wrong? Is there another way of storing and accessing this type of data in dart if my method is completely wrong?
Map<int,List<int>> m;
m[0]=[];
m[0].add(5);
You have to initialise it with empty map first
Map<int, List<int>> m={}; //<- initialise it here
m[0] = [];
m[0].add(5);
print(m); // prints {0: [5]}

Wicket NumberTextField in Kotlin throws ClassCastException when submitted

I'm having some issues with a Wicket (8.0.0-M4) NumberTextField in Kotlin (1.1.0).
My stripped-down form looks like this:
class Test : AbstractWebPage() {
val housenumberModel: Model<Int> = Model<Int>()
val housenumber = NumberTextField<Int>("housenumberModel", housenumberModel)
val form: Form<Unit> = object : Form<Unit>("adressForm") {}
override fun onInitialize() {
super.onInitialize()
form.add(housenumber.setRequired(false))
form.add(object : SubmitLink("submit") {
override fun onSubmit() {
super.onSubmit()
println(housenumberModel.`object`) // this is line 28
}
})
add(form)
}
}
After submitting the form I get the following stacktrace:
java.lang.ClassCastException: java.lang.String cannot be cast to
java.lang.Number
at com.mycompany.test.pages.Test$onInitialize$1.onSubmit(Test.kt:28)
at org.apache.wicket.markup.html.form.Form.delegateSubmit(Form.java:1312)
at org.apache.wicket.markup.html.form.Form.process(Form.java:979)
at org.apache.wicket.markup.html.form.Form.onFormSubmitted(Form.java:802)
at org.apache.wicket.markup.html.form.Form.onRequest(Form.java:715)
at org.apache.wicket.core.request.handler.ListenerRequestHandler.internalInvoke(ListenerRequestHandler.java:301)
at org.apache.wicket.core.request.handler.ListenerRequestHandler.invoke(ListenerRequestHandler.java:250)
at org.apache.wicket.core.request.handler.ListenerRequestHandler.invokeListener(ListenerRequestHandler.java:210)
at org.apache.wicket.core.request.handler.ListenerRequestHandler.respond(ListenerRequestHandler.java:203)
at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:912)
at org.apache.wicket.request.RequestHandlerExecutor.execute(RequestHandlerExecutor.java:65)
at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:283)
at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:253)
at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:221)
at org.apache.wicket.protocol.http.WicketFilter.processRequestCycle(WicketFilter.java:262)
at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:204)
at org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:286)
[...]
If I use
val housenumberModel: Model<Int> = Model.of(0)
instead of
val housenumberModel: Model<Int> = Model<Int>()
everything works fine. But since my NumberTextField is optional I don't want to have it pre-initialized with 0.
Me and my colleagues were trying to change the type signature of the Model in every way we could imagine but came to no solution. A co-worker suggested to write a custom Wicket converter since Kotlins Int is represendeted as a primitive type (From the docs: "On the JVM, non-nullable values of this type are represented as values of the primitive type int.") Even though I don't know yet if this would work it seems like an overkill for me.
Another hack I could think of: writing some JavaScript to delete the zero from the input field. Also not really something I would want to do.
Question: Is there a simple solution to my problem?
(And as a bonus-question: has already anyone written a larger Wicket application in Kotlin and could tell me if this combination is ready for prime time to develop a critical project with this stack or is my problem just the tip of the iceberg?)
[edit]
Solution as pointed out by svenmeier:
Using
val housenumber = NumberTextField<Int>("housenumberModel", housenumberModel, Int::class.java)
works.
Or as an alternative:
val housenumbervalue: Int? = null
val housenumberModel: IModel<Int> = PropertyModel<Int>(this, "housenumbervalue")
val housenumber = NumberTextField<Int>("housenumberModel", housenumberModel)
Because of type erasure your NumberTextField cannot detect the generic type parameter of your model. Since your model object is null, it cannot be used to derive the type either.
In this case Wicket assumes a String model object type :/.
Either provide the type to the NumberTextField explicitly, or use a model that keeps its generic information, e.g. a PropertyModel.
There is a way to tell wicket about the type you want, it is by adding the type in the constructor. More here.
In Java it looks like this:
new NumberTextField<Integer>("housenumberModel", housenumberModel, Integer.class);

Reassign ArrayList in a better Way

The below code is working, but its looking odd to me, is there any better way to this.
var res:scala.collection.mutable.LinkedHashMap[String,scala.collection.immutable.Map[String,String]]=??
var arList = new ArrayList[String]()
res.keySet.map(arList.add(_))
//here res key set changed so i want to reassign the list by new keySet
res=?? //updated
arList.clear
res.keySet.map(arList.add(_))
its looking very odd that to call the .clear on arList
You can use default JavaConverters.
import scala.collection.JavaConverters._
val list = new java.util.ArrayList(res.keySet.asJavaCollection)
I didn't get why do you need to do clear, is it some requirement that you pass ArrayList once and update it's content later?