【问题标题】:Inserting into HashMap messes with sorting插入 HashMap 会导致排序混乱
【发布时间】:2019-11-21 20:28:47
【问题描述】:

基于这个类

public class Record {
    public static final String TABLE_NAME = "records";

    public static final String COLUMN_ID = "id";
    public static final String COLUMN_LONGITUDE = "longitude";
    public static final String COLUMN_LATITUDE = "latitude";
    public static final String COLUMN_SPEED = "speed";
    public static final String COLUMN_TIMESTAMP = "timestamp";

    private int id;
    private String longitude;
    private String latitude;
    private String speed;
    private String timestamp;

    public static final String CREATE_TABLE =
            "CREATE TABLE " + TABLE_NAME + "("
                + COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
                + COLUMN_LONGITUDE + " TEXT,"
                + COLUMN_LATITUDE + " TEXT,"
                + COLUMN_SPEED + " TEXT,"
                + COLUMN_TIMESTAMP + " TIMESTAMP DEFAULT (DATETIME('now','localtime'))"
            + ")";

    public Record(){
    }

    public Record(int id, String longitude, String latitude, String speed, String timestamp){
        this.id = id;
        this.longitude = longitude;
        this.latitude = latitude;
        this.speed = speed;
        this.timestamp = timestamp;
    }

    public int getId(){
        return id;
    }

    public String getLongitude(){
        return longitude;
    }

    public String getLatitude(){
        return latitude;
    }

    public String getSpeed(){
        return speed;
    }

    public String getTimestamp(){
        return timestamp;
    }

    public void setId(int id){
        this.id = id;
    }

    public void setLongitude(String longitude){
        this.longitude = longitude;
    }

    public void setLatitude(String latitude){
        this.latitude = latitude;
    }

    public void setSpeed(String speed){
        this.speed = speed;
    }

    public void setTimestamp(String timestamp){
        this.timestamp = timestamp;
    }
}

我已经创建了我的 SQLite 模型

public class DatabaseHelper extends SQLiteOpenHelper {

    private static final int DATABASE_VERSION = 1;

    // Database Name
    private static final String DATABASE_NAME = "speeds";

    public DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(Record.CREATE_TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + Record.TABLE_NAME);

        onCreate(db);
    }

    public void insertRecord(String longitude, String latitude, String speed){
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();

        values.put(Record.COLUMN_LONGITUDE, longitude);
        values.put(Record.COLUMN_LATITUDE, latitude);
        values.put(Record.COLUMN_SPEED, speed);

        System.out.println("VALUEEEEEEEES" + values);

        db.insert(Record.TABLE_NAME, null, values);
        db.close();
    }

    public List<Record> getAllRecords(){
        List<Record> records = new ArrayList<>();

        String selectQuery = "SELECT * FROM " + Record.TABLE_NAME + " ORDER BY " + Record.COLUMN_TIMESTAMP + " DESC";

        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);

        if(cursor.moveToFirst()){
            do{
                Record record = new Record();
                record.setId(cursor.getInt(cursor.getColumnIndex(Record.COLUMN_ID)));
                record.setLongitude(cursor.getString(cursor.getColumnIndex(Record.COLUMN_LONGITUDE)));
                record.setLatitude(cursor.getString(cursor.getColumnIndex(Record.COLUMN_LATITUDE)));
                record.setSpeed(cursor.getString(cursor.getColumnIndex(Record.COLUMN_SPEED)));
                record.setTimestamp(cursor.getString(cursor.getColumnIndex(Record.COLUMN_TIMESTAMP)));

                records.add(record);
            } while (cursor.moveToNext());
        }
        db.close();

        return records;
    }

    public List<Record> getLastTenRecords(){
        List<Record> records = new ArrayList<>();

        String selectQuery = "SELECT * FROM " + Record.TABLE_NAME + " ORDER BY " + Record.COLUMN_TIMESTAMP + " DESC LIMIT 10";

        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);

        if(cursor.moveToFirst()){
            do{
                Record record = new Record();
                record.setId(cursor.getInt(cursor.getColumnIndex(Record.COLUMN_ID)));
                record.setLongitude(cursor.getString(cursor.getColumnIndex(Record.COLUMN_LONGITUDE)));
                record.setLatitude(cursor.getString(cursor.getColumnIndex(Record.COLUMN_LATITUDE)));
                record.setSpeed(cursor.getString(cursor.getColumnIndex(Record.COLUMN_SPEED)));
                record.setTimestamp(cursor.getString(cursor.getColumnIndex(Record.COLUMN_TIMESTAMP)));

                records.add(record);
            } while (cursor.moveToNext());
        }
        db.close();

        return records;
    }
}

现在,我正在尝试在 ExpandableListView 中显示一些数据。在我的场景中,我按COLUMN_TIMESTAMP 对sql 查询的响应进行排序,并尝试以HashMap&lt;String , List&lt;String&gt; 的类型对其进行解析,以便ExpandableListView 识别它。

问题是,即使结果是排序的(循环打印的时候也能看到),我用这种方法解析放入HashMap后,排序就没有了。

public static HashMap<String, List<String>> getLastTenData(Context context) {
        HashMap<String, List<String>> expandableListDetail = new HashMap<>();

        DatabaseHelper databaseHelper = new DatabaseHelper(context);

        List<Record> recordList = databaseHelper.getLastTenRecords();
        for(int i=0; i<recordList.size(); i++){
            List<String> myList = new ArrayList<>();
            myList.add("Y: "+recordList.get(i).getLatitude());
            myList.add("X: " + recordList.get(i).getLongitude());
            myList.add("Km/h: "+recordList.get(i).getSpeed());
            expandableListDetail.put(recordList.get(i).getTimestamp(), myList);
            System.out.println("check "+String.valueOf(i)+"    "+recordList.get(i).getTimestamp());
        }

        System.out.println(expandableListDetail);

        return expandableListDetail;
    }

我的意思是,expandableListDetail 没有按应键排序。 有什么帮助吗?

【问题讨论】:

  • 只需使用LinkedHashMap 而不是new HashMap&lt;&gt;()
  • @Deadpool 哇,这太容易了……你无法想象我被困在这上面多久了。
  • 您也可以使用TreeMap,它根据密钥订购商品,例如使用键 c、a、b 将 3 个项目放入地图中,迭代时将导致 a、b、c 排序。另一方面,LinkedHashMap 将保留项目首先放入地图的顺序,而不管键顺序如何;所以在前面的例子中,它会导致 c、a、b 排序

标签: java android hashmap


【解决方案1】:

如果已经回答过类似的问题(关于HashSethere

类似地,HashMap 是无序的,因此向其添加值然后迭代地图将不会按照您最初添加的顺序生成项目。

为什么LinkedHashMap 解决了这个问题? (从@Deadpool 那里汲取灵感)

Map接口的哈希表和链表实现,带有 可预测的迭代顺序。此实现不同于 HashMap 因为它维护一个双向链表,贯穿其所有 条目。这个链表定义了迭代顺序,即 通常是键插入地图的顺序 (插入顺序)。

为什么TreeMap 解决了这个问题? (从@tomgeraghty3 中汲取灵感)

地图根据其键的自然顺序进行排序

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-05
    • 1970-01-01
    相关资源
    最近更新 更多