French Les Map me font peur :(

Serge Bertet

Active Member
Licensed User
Salut,
je stocke des données (paires clefs/valeurs) dans des Maps mais il est précisé que ces structures de données ne conservent pas l'ordre de stockage.
Déjà je ne vois pas dans quel cas l'ordre serait perdu (fragmentation de la mémoire ?).
Mes Map ne contiennent que quelques centaines de clefs/valeurs (200, 300 ?), je ne pense pas que ça arrive souvent.
Est-ce qu'il existe d'autres types de données par paire ?
J'ai bien pensé créer une liste de type personnalisé et stocker ça avec RandomAccessFile mais je trouve que ça fait lourd pour si peu.
Il reste KeyValueStore aussi, et créer un fichier BDD à chaque fois ?... Possible ?
Merci.
 

zed

Active Member
Licensed User
Tu peux simplement stocker tes données dans une DB SQLite. C'est très rapide et tu fais ce que tu veux avec.
 

Grinaute

Member
Licensed User
Longtime User
Salut Serge,

voici un exemple vite fait et non testé :

B4X:
Sub Process_Globals
    Dim SQL1 As SQL
End Sub

Sub Globals
    Private EditTextKey As EditText
    Private EditTextValue As EditText
End Sub

Sub Activity_Create(FirstTime As Boolean)
    If FirstTime Then
        InitializeDatabase
    End If
   
    ' Créer l'interface utilisateur ici
End Sub

Sub InitializeDatabase
    If File.Exists(File.DirInternal, "mapdata.db") = False Then
        SQL1.Initialize(File.DirInternal, "mapdata.db", True)
        CreateTable
    Else
        SQL1.Initialize(File.DirInternal, "mapdata.db", False)
    End If
End Sub

Sub CreateTable
    SQL1.ExecNonQuery("CREATE TABLE IF NOT EXISTS MapData (id INTEGER PRIMARY KEY AUTOINCREMENT, key TEXT UNIQUE, value TEXT)")
End Sub

Sub AddEntry
    Dim key As String = EditTextKey.Text
    Dim value As String = EditTextValue.Text
   
    SQL1.ExecNonQuery2("INSERT OR REPLACE INTO MapData (key, value) VALUES (?, ?)", Array As String(key, value))
    ToastMessageShow("Entrée ajoutée/mise à jour avec succès", False)
End Sub

Sub UpdateEntry
    Dim key As String = EditTextKey.Text
    Dim value As String = EditTextValue.Text
   
    SQL1.ExecNonQuery2("UPDATE MapData SET value = ? WHERE key = ?", Array As String(value, key))
    ToastMessageShow("Entrée mise à jour avec succès", False)
End Sub

Sub DeleteEntry
    Dim key As String = EditTextKey.Text
   
    SQL1.ExecNonQuery2("DELETE FROM MapData WHERE key = ?", Array As String(key))
    ToastMessageShow("Entrée supprimée avec succès", False)
End Sub

Sub RetrieveEntry
    Dim key As String = EditTextKey.Text
    Dim cursor As Cursor
   
    cursor = SQL1.ExecQuery2("SELECT value FROM MapData WHERE key = ?", Array As String(key))
    If cursor.RowCount > 0 Then
        cursor.Position = 0
        EditTextValue.Text = cursor.GetString("value")
    Else
        EditTextValue.Text = ""
        ToastMessageShow("Clé non trouvée", False)
    End If
    cursor.Close
End Sub
 

Serge Bertet

Active Member
Licensed User
Oui, merci à vous, je pensais à quelque chose de moins lourd vu que c'est pour stocker sur carte SD que les utilisateurs pourraient se passer.
Je fais le test avec KeyValueStore pour l'instant.
J'aurais aimé un format texte, plus facile à interpréter au cas où ....
 

drgottjr

Expert
Licensed User
Longtime User
les maps ne sont pas censes garder l'ordre d'insertion/addition;
on a des arrays ou des lists pour cela.
si les elements sont ranges, la rechereche est lente; il faut
commencer par le premier element et chercher jusqu'a l'element
d'interet ne soit trouve. les maps ont ete inventes pour
chercher rapidement. ils utilisent un "arbre" pour ranger les
donnees. main - helas - cet arbre ne garde pas d'ordre particulier.

les bases de donnees utilisent un arbre (index) pour faciliter les recherches.
mais il faut declarer cet index en creant la bd. si non, c'est un simple list.
et chercher une base de donnees non-indexee n'est plus rapide que de chercher un
simple list en memoire. ces arbres - dans ou en dehors d'une base de donnees -
il y en a plusiers types. un map en utilise une espece. qui fonctionne bien, d'ailleurs.

donc, pour avoir access a des elements ranges, il faut un list/array. pour avoir
access rapide a ces memes elements, il faut un map. 2 structures - comptez-les - 2.
c'est exactement ce que fait un base de donnees.

a noter: il existe un b4xorderedmap - c'est a dire - une combinaison d'un map et d'un
list. comme je disais: 2 structures pour garder l'ordre et pour faciliter la recherche.

dans l'exemple ci-dessus, la declaration:
SQL1.ExecNonQuery("CREATE TABLE IF NOT EXISTS MapData (id INTEGER PRIMARY KEY AUTOINCREMENT, key TEXT UNIQUE, value TEXT)")
specifie 2 index/arbres avec "PRIMARY KEY" et "TEXT UNIQUE". sans ces declarations, c'est un simple list range mais sans recherche rapide. dans l'exemple, on a effectivement 3 structures: les elements, un map pour la recherche rapide par "id", et un map pour la recherche rapide par "key". 3 - comptez-les - 3.
 

Serge Bertet

Active Member
Licensed User
J'ai choisi la solution b4xorderedmap mais à ma sauce, ça fait quand même bizarre ce mix list/map. mais ça fonctionne.
Échange entre fichier et map par des chaines JSON, transformation en list pour la fonction de tri.
Merci.
 

William Lancee

Well-Known Member
Licensed User
Longtime User
It hasn't been mentioned yet, but in B4J and B4A, the Map object maintains order. In B4i, this is NOT the case.
So, depending on your audience, you may not have to worry about that.
 

Serge Bertet

Active Member
Licensed User
Thank you Bill, it is good to know that.
 

aeric

Expert
Licensed User
Longtime User
Voici une autre option
 
Top