Android Example Praise to the data type Map.

As you know, Map is a kind of list of pairs of data; each pair is composed of a key and a value which can be of any type.

An example that I believe can be useful:

You have a beautiful table SQLite. This table contains some fields:

ID INTEGER Primary Key
Name TEXT
Age INTEGER
Other ... many.

Create a class related to this table:

clsPerson:
B4X:
'Class module - clsPerson
Sub Class_Globals

#Region  Properties member variables
    Private mID As Int
    Private mName As String
    Private mAge As Int
#End Region

End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize(ID As Int, Name As String)
    mID = ID
    mName = Name
End Sub


#Region  + P R O P E R T I E S

' ID
Public Sub setID(ID As Int)
    mID = ID
End Sub
Public Sub getID As Int
    Return mID
End Sub

' Name
Public Sub setName(Name As String)
    mName = Name
End Sub
Public Sub getName As String
    Return mName
End Sub

' Age
Public Sub setAge(Age As Int)
    mAge = Age
End Sub
Public Sub getAge As Int
    Return mAge
End Sub

#End Region

#Region  + M E T H O D S
#End Region

Now you could use a Map to store all records (in memory!), filling the Map with data taken from DB, creating an Item for the great class of Informatix CheckList and load the data in item by taking them from the Map.
(I wrote an excessive synthesis; eventually I will post a complete example).

B4X:
Private DB As SQL
' OMISSIS: Open the DB

Private mapPersons As Map : mapPersons.Initialize

Private Query As String = "SELECT * FROM Person"
Private Cur As Cursor
Cur = DB.ExecQuery(Query)

Private ID, Age As Int
Private Name As String
For r = 0 To Cur.RowCount - 1
    Cur.Position = r

    ID = Cur.GetInt("ID")
    Name = Cur.GetString("Name")
    Age = Cur.GetInt("Age")

    Private Person As clsPerson
    Person.Initialize(ID, Name)
    Person.Age = Age

    mapPersons.Put(ID, Person)
Next

DB.Close
 
Last edited:

seardnA

Member
Licensed User
Longtime User
Hi Luca,
Could you please add more flesh to your interesting example.
Let's stick with this example.

I create a class with 3 parameters (ID, First name, last name)
I create 6 methods to get or set the value for these parameters.

you create an object of the class person and get there data by entries from a user.
Now I want to store that user specific data in a database.

I learn now that map is a efficient way to store the data.
I also see that DBUtils requires a map in its "create table" sub.

I do not understand how to create a map form that object?

Can you help?

Thanks,
Andreas
 

LucaMs

Expert
Licensed User
Longtime User
CreateTable only aim is to create the table structure.
It receives a map consisting of field names and field types as string.

Private mapMyTableFields As Map
mapMyTableFields.Initialize
mapMyTableFields.Put("ID", "INT")
mapMyTableFields.Put("FirstName", "TEXT")
mapMyTableFields.Put("LastName", "TEXT")

CreateTable(SQL, TableName, mapMyTableFields, "ID")
 

LucaMs

Expert
Licensed User
Longtime User
Another reason to use the Maps:

You have a custom class clsPerson with a property Name.

You can not cycle on a "List of Person" like:
B4X:
Dim lstPersons As List : lstPersons.Initialize

Dim P As clsPerson : P.Initialize : P.Name = "Erel"
lstPersons.Add(P)

Dim P As clsPerson : P.Initialize : P.Name = "MyName"
lstPersons.Add(P)

For Each Person As clsPerson In lstPerson
    Log(Person.Name)
Next


but you can:
B4X:
Dim mapPersons As Map : mapPersons.Initialize

Dim P As clsPerson : P.Initialize : P.Name = "Erel"
mapPersons.Put(0, P)

Dim P As clsPerson : P.Initialize : P.Name = "MyName"
mapPersons.Put(1, P)

For Each Person As clsPerson In mapPersons.Values
    Log(Person.Name)
Next



(Yes, I know that you can not have a "List of Person" but only a "List of String")
 
Last edited:

Widget

Well-Known Member
Licensed User
Longtime User
Another reason to use the Maps:

You have a custom class clsPerson with a property Name.

You can not cycle on a "List of Person" like:
B4X:
Dim lstPersons As List : lstPersons.Initialize

Dim P As clsPerson : P.Initialize : P.Name = "Erel"
lstPersons.Add(P)

Dim P As clsPerson : P.Initialize : P.Name = "MyName"
lstPersons.Add(P)

For Each Person As clsPerson In lstPerson
    Log(Person.Name)
Next

(Yes, I know that you can not have a "List of Person" but only a "List of String")

@LucasMS,

I don't understand why we can't have a List that stores clsPerson. Your example above DOES WORK. (If you correct the minor syntax error to P.Initialize(0,"Erel"))

I'm new to B4A so has B4A 5.80 changed recently to support this? Or did I miss something in your example?
Would a Map be more efficient than a List when storing a class instance? (A Map does have an advantage of being able to store a key for the clsPerson so retrieval for a certain class instance would be faster.) Either way I think storing a Class in a List or Map is pretty awesome. :)
TIA
 

Widget

Well-Known Member
Licensed User
Longtime User
I did not write you can not create a "list of classes" but that you can not cycle on it with a "For Each" as you can using a Map (see the example in #4).

I tried it and it does work on a List (using B4a v5.80) (from post #4)
Maybe it didn't work in a prior version?

B4X:
For Each Person As clsPerson In lstPerson
  Log(Person.Name)
Next
 

LucaMs

Expert
Licensed User
Longtime User
This is an old thread but I want to add a tip.

Never use a "For Each" loop to get items placed on a Map! They will not be returned in the same order in which they were added.

Because of it I lost some gray cells and I wasted a lot of time.
 

LucaMs

Expert
Licensed User
Longtime User
This is incorrect. The recommended way to iterate over Map items is with For Each. It will return the items in the same order that they were added (in B4A and B4J, not in B4i). Generally speaking if you are using a Map then in most cases the insertion order shouldn't matter.
I used a Map with B4J and I got that problem. It's "fresh" :) so I can (must) do more tests but it seem to be so to me.

Because I swear of your words, now I'm in crisis :D, I have to check that it is not a different error.
 

LucaMs

Expert
Licensed User
Longtime User
I have spent days (not many hours / day, actually) to discover the error; I thought I had found it, and now... I want to find out why the project now works despite the fact that the "For Each" is not the error, spending other days :p
 

LucaMs

Expert
Licensed User
Longtime User
Good news: my project(s) is still full of bugs :p

:(

Why do I think so often to throw everything and start over instead of looking for errors patiently? :mad:
[Most likely because my every project seems like a "spaghetti" project, although it is not so]
 

Informatix

Expert
Licensed User
Longtime User
This is an old thread but I want to add a tip.

Never use a "For Each" loop to get items placed on a Map! They will not be returned in the same order in which they were added.

Because of it I lost some gray cells and I wasted a lot of time.
Order is not guaranteed with maps under Android, whatever method you use to read them.
From the Android API documentation: "This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time."

EDIT: please read post #17
 
Last edited:

LucaMs

Expert
Licensed User
Longtime User
Order is not guaranteed with maps under Android, whatever method you use to read them.
From the Android API documentation: "This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time."
So I should remove all this thread because I'm starting to love maps (in Android) a little bit less :D

Many thanks, @Informatix.

Then the bug in my project may be due precisely to this; in fact, it occurs randomly. I will be forced to use a bidimensional Array and also an integer as index No, I can't
 

Informatix

Expert
Licensed User
Longtime User
So I should remove all this thread because I'm starting to love maps (in Android) a little bit less :D

Many thanks, @Informatix.

Then the bug in my project may be due precisely to this; in fact, it occurs randomly. I will be forced to use a bidimensional Array and also an integer as index No, I can't
I checked the B4A map implementation after writing my post and I realized that I was wrong. The Java class is LinkedHashMap, not HashMap, so the order is guaranteed (identical to the insertion order). Sorry for the wrong information.
 
Top