【问题标题】:Why doen't this for loop work?为什么这个 for 循环不起作用?
【发布时间】:2013-12-13 01:23:32
【问题描述】:

这是一个从两个不同的 JSON URL 获取数据的安卓应用。然后我想混合他们的数据并将它们放在地图中。为此,我使用了嵌套的 for 循环。但问题是它只显示 YEARS 和 SYSTEMDATA2 而不是 SYSTEMDATA1。我认为我的嵌套循环不正确。

有人知道原因吗?

for(int i = 0; i < array2System1.length(); i++){
        c1 = array2System1.getJSONObject(i);

        for(int x = 0; x < array2System2.length(); x++){

            c2 = array2System2.getJSONObject(x);

            }

        //Storing JSON item in a Variable
        valueSystem2 = c2.getString(SYSTEMDATA2);
        year = c1.getString(YEAR);
        valueSystem1 = c1.getString(SYSTEMDATA1);

         // Adding value HashMap key => value
         HashMap<String, String> map = new HashMap<String, String>();
         map.put(SYSTEMDATA1, valueSystem1);
         map.put(SYSTEMDATA2, valueSystem2);
         map.put(YEAR, year);


         mylist.add(map);
         list=(ListView)findViewById(R.id.list);

         ListAdapter adapter = new SimpleAdapter(Search.this, mylist,
                    R.layout.list_M,
                    new String[] {SYSTEMDATA1, SYSTEMDATA2, YEAR}, new int[] {
                            R.id.systemData1, R.id.systemData2, R.id.years});

         mylist.setAdapter(adapter);
    }

结果应该是这样的 年份值(SYSTEMDATA2) 值(SYSTEMDATA1)

当前问题 它没有显示其中一个值。 (系统数据 1 或系统数据 2) http://i40.tinypic.com/2wqykvr.png

新更新

        //Getting JSON Array
        JSONObject myJson1 = jsons[0];
        JSONObject myJson2 = jsons[1];
        try {
            List<Map<String, String>> listValues = new ArrayList<Map<String, String>>();



            JSONArray array1C1 = myJson1.getJSONArray("myDATA");
            JSONArray array2C1 = array1C1.getJSONArray(1);

            JSONArray array1C2 = myJson2.getJSONArray("myDATA");
            JSONArray array2C2 = array1C2.getJSONArray(1);

            for (int i=0; i<array2C1.length(); i++)
            {
                JSONObject entryJsonC1 = array2C1.getJSONObject(i);


                String val1 = entryJsonC1.getString(SYSTEMDATA1);

                String year = entryJsonC1.getString("date");


                    JSONObject entryJsonC2 = array2C2.getJSONObject(i);

                    String val2 = entryJsonC2.getString(SYSTEMDATA2);


                Map<String, String> map = new HashMap<String, String>();
                map.put(SYSTEMDATA1, val1);
                map.put(SYSTEMDATA2, val2);
                map.put(YEAR, year);


                listValues.add(map);

            }

            list = (ListView) findViewById(R.id.list);


            String[] adaptersKeys = new String[] {SYSTEMDATA1, SYSTEMDATA2, YEAR};
            int[] adapterViews = new int[] {R.id.systemData1, R.id.systemData2, R.id.years};
            ListAdapter adapter = new SimpleAdapter(MultiMainActivity.this, listValues, R.layout.list2, adaptersKeys, adapterViews);

            list.setAdapter(adapter);

        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

现在的结果是:YEAR SAME-VALUE SAME-VALUE

【问题讨论】:

  • 您的第二个 for 循环在第 8 行以 } 结束,而它应该更晚结束。
  • 查看我的答案,您可能还有setAdapter 方法的另一个错误。我还对您的代码进行了一些优化,但仍然可以完善。
  • 您能否发布(至少部分):array2System1、array2System2 的内容,并解释一下您希望如何将它们混合到地图中 - 所以混合后的地图内容示例。
  • @Melquiades 刚刚更新了我的帖子。请看一看。
  • 嗨@DannyJj,请看我的回答

标签: java android json for-loop hashmap


【解决方案1】:

因为你已经定义了这个:

private static final String SYSTEMDATA1 = "value";
private static final String SYSTEMDATA2 = "value";

//you can't have 2 entries with the same key
private static final String SYSTEMDATA2_KEY = "value2";

问题出现在您创建地图的位置:

// Adding value HashMap key => value
HashMap<String, String> map = new HashMap<String, String>();
map.put(SYSTEMDATA1, valueSystem1);
map.put(SYSTEMDATA2_KEY, valueSystem2);
map.put(YEAR, year);

A Map 是:

将键映射到值的对象。地图不能包含重复的键;每个键最多可以映射到一个值

来自 put() 方法的文档:

将指定值与此映射中的指定键关联(可选操作)。 如果映射先前包含键的映射,则旧值将替换为指定值。

因此,您使用 SYSTEMDATA1 作为键放置 valueSystem1,即“值”,然后使用 SYSTEMDATA2 作为键放置 valueSystem2,这也是“值”,因此您正在覆盖 valueSystem1!

请参阅下面的编辑...

编辑:

我猜要检索您的值,您必须使用“值”的键,这很好,但是稍后要插入到地图中,您必须有唯一的键。如果您仍然有 SYSTEMDATA1="value" 和 SYSTEMDATA2="value",请再添加一个用于存储在地图中以及稍后存储在适配器中:

//you can't have 2 entries with the same key
private static final String SYSTEMDATA2_KEY = "value2";

// Create a new Map
Map<String, String> map = new HashMap<String, String>();
map.put(SYSTEMDATA1, val1);
map.put(SYSTEMDATA2_KEY, val2);
map.put(YEAR, year);

然后,当您设置适配器键时:

// Create a new adapter to attach this listView
String[] adapterKeys = new String[] {SYSTEMDATA1, SYSTEMDATA2_KEY, YEAR};

在我的原始答案中更新了代码。

【讨论】:

  • 是的,我明白了。谢谢你的解释。我现在用地图重做。但它仍然显示两个值的相同数据。我猜在地图中它不应该被覆盖,是吗?!我从@Manitoba 和他的最新答案中得到了帮助。因此,如果您检查一下并了解它为什么不断覆盖值,那就太好了。
  • 把你帖子里的代码更新到现在的状态,我去看看。
  • 请检查新更新位。我也保留了旧的整个文件,所以你也看到了。谢谢
  • 在您的新更新中,我没有看到 SYSTEMDATA1 和 SYSTEMDATA2 的值,所以我假设它们都是相同的(“值”)。请查看我的更新。
【解决方案2】:
List<Map<String, String>> listValues = new ArrayList<Map<String, String>>();

JSONArray jsonArray = new JSONArray(.....); // Contains all the indicators
for (int i=0; i<jsonArray.length(); i++)
{
    JSONObject entryJson = jsonArray.getJsonObject(i);

    // Check integrity
    if (!entryJson.hasKey("country")) throw new Exception("No 'country' key found");
    if (!entryJson.hasKey("value")) throw new Exception("No 'value' key found");
    if (!entryJson.hasKey("date")) throw new Exception("No 'date' key found");

    // Get country
    JSONObject countryJson = entryJson.getJsonObject("country");
    if (!countryJson.hasKey("value")) throw new Exception("No 'value' key found");
    String country = countryJson.getString("value");

    // Get population
    String population = entryJson.getString("value");

    // Get year
    String year = entryJson.getString("date");

    // Create a new Map
    Map<String, String> map = new HashMap<String, String>();
    map.put(SYSTEMDATA1, country);
    map.put(SYSTEMDATA2, population);
    map.put(YEAR, year);

    // Add to list
    listValues.add(map);
}

// Get the ListView
ListView Llist = (ListView) findViewById(R.id.list);

// Create a new adapter to attach this listView
String[] adapterKeys = new String[] {SYSTEMDATA1, SYSTEMDATA2, YEAR};
int[] adapterViews = new int[] {R.id.systemData1, R.id.systemData2, R.id.years};
ListAdapter adapter = new SimpleAdapter(Search.this, listValues, R.layout.list_M, adapterKeys, adapterViews);

// Attach the adapter to the listView
Llist.setAdapter(adapter);

这是另一种效果更好的方法。我没有测试代码,因为它是在记事本中制作的。如果您有任何问题,请告诉我。

【讨论】:

  • 感谢您的帮助。有一些问题,但听起来它接近工作。首先,我应该在 try { 中有这段代码吗?正确的?其次,它不接受hasKey,并希望我将其转换或更改为has。我改成has了,所以没有错误并遵守,但是页面是空的。
  • 顺便问一下,SONArray jsonArray = new JSONArray(.....); 是什么意思?!你能根据我的情况举一个例子吗?我想这部分是我得到空白页面的原因。
  • 好的,我可以让它工作。只需要在最后添加list.setAdapter(adapter);。但我支持同样的问题,我开始了。它显示两个国家的相同值。相同的号码。 ://
【解决方案3】:

第二个 for 循环很早就结束了。应该如下。

for(int x = 0; x < array2System2.length(); x++){

            c2 = array2System2.getJSONObject(x);

        //Storing JSON item in a Variable
        valueSystem2 = c2.getString(SYSTEMDATA2);
        year = c1.getString(YEAR);
        valueSystem1 = c1.getString(SYSTEMDATA1);

         // Adding value HashMap key => value
         HashMap<String, String> map = new HashMap<String, String>();
         map.put(SYSTEMDATA1, valueSystem1);
         map.put(SYSTEMDATA2, valueSystem2);
         map.put(YEAR, year);
         mylist.add(map);
} // This is where it should get closed

否则,您只是重新分配 c2 变量并丢失除最后一个值之外的其他值。现在,您可以将 valueSystem1、valueSystem2 和 YEAR 值放在 map 中,然后添加到列表中。希望这会有所帮助

【讨论】:

  • 谢谢,但我刚刚检查过了。它仍然不显示 SYSTEMDATA1 并且每年都会重复每个值。请查看图片:link
  • 这个应用有点大,但目前我正在关注this tutorial。但有 2 个网址。如果您认为有问题,我会发布我自己的主要活动。
  • 猜想——我认为 HashMap 应该在第一个 for 循环中创建,而不是在第二个循环中,并且 mylist.add(map) 也应该在第二个 for 循环之外,即第一个 for 循环。
【解决方案4】:

您需要将所有代码放在内部循环中。目前您只需关闭内部循环 - 它运行并覆盖 c2 并且什么都不做。

类似:

for(int i = 0; i < array2System1.length(); i++){
    c1 = array2System1.getJSONObject(i);

    for(int x = 0; x < array2System2.length(); x++){
        c2 = array2System2.getJSONObject(x);

        //Storing JSON item in a Variable
        valueSystem2 = c2.getString(SYSTEMDATA2);
        year = c1.getString(YEAR);
        valueSystem1 = c1.getString(SYSTEMDATA1);

        // Adding value HashMap key => value
        HashMap<String, String> map = new HashMap<String, String>();
        map.put(SYSTEMDATA1, valueSystem1);
        map.put(SYSTEMDATA2, valueSystem2);
        map.put(YEAR, year);

        mylist.add(map);
    }
}

【讨论】:

    【解决方案5】:
    for(int i=0; i<array2System1.length(); i++)
    {
        c1 = array2System1.getJSONObject(i);
        year = c1.getString(YEAR);
        valueSystem1 = c1.getString(SYSTEMDATA1);
    
        for(int x=0; x<array2System2.length(); x++)
        {
            c2 = array2System2.getJSONObject(x);
    
            //Storing JSON item in a Variable
            valueSystem2 = c2.getString(SYSTEMDATA2);
    
            // Adding value HashMap key => value
            HashMap<String, String> map = new HashMap<String, String>();
            map.put(SYSTEMDATA1, valueSystem1);
            map.put(SYSTEMDATA2, valueSystem2);
            map.put(YEAR, year);
    
            mylist.add(map);
        }
    }
    
    list = (ListView)findViewById(R.id.list);
    
    ListAdapter adapter = new SimpleAdapter(Search.this, mylist, R.layout.list_M, new String[] {SYSTEMDATA1, SYSTEMDATA2, YEAR}, new int[] {R.id.systemData1, R.id.systemData2, R.id.years});
    
    // Shoudl be list and not mylist
    list.setAdapter(adapter);
    

    【讨论】:

    • 或类似的东西。
    • 谢谢,但没用。请查看图片link
    • 你可以在这里发布你的 JSON 吗?
    • 在我的应用程序中,我有一个 url 构建器,它从特定的 api 创建一个 json url。但是json的布局和语法总是一样的。这是一个例子。 api.worldbank.org/countries/ca/indicators/… 你也可以更改年份国家。例如。 ca 代表加拿大
    猜你喜欢
    • 1970-01-01
    • 2019-07-23
    • 2010-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多