Concurrent modification exception for list - android

Can anybody tell me where I am going wrong here?
File promoCountFile = new File(RaconTours.PATH + "promocodeCount.txt");
if (promoPlistPath.exists()) {
try {
ObjectInputStream inStream = new ObjectInputStream(new FileInputStream(promoPlistPath));
ObjectInputStream promoStream = new ObjectInputStream(new FileInputStream(promoCountFile));
promoobj = (ArrayList<HashMap<String, Object>>) promoStream.readObject();
obj = (ArrayList<HashMap<String, Object>>) inStream.readObject();
for (HashMap<String, Object> tmpObj : obj) {
promoTourname = (String) tmpObj.get("promoTour");
promocodeID = (String) tmpObj.get("promocode");
if (promoTourname.equals(currentTour.getObjtourName())) {
//if the condition is met, remove the entry from the file
for (HashMap<String, Object> promoTemp : promoobj) {
promoTourCount = (Integer) promoTemp.get("promocodeTourCount");
}
obj.remove(tmpObj);
--promoTourCount;
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(promoPlistPath));
out.writeObject(obj);
out.close();
ObjectOutputStream promoout = new ObjectOutputStream(new FileOutputStream(promoCountFile));
HashMap<String, Object> promoCountDict = new HashMap<String, Object>();
promoobj.remove(0);
promoCountDict.put("promocodeTourCount",promoTourCount);
promoobj.add(promoCountDict);
promoout.writeObject(promoobj);
promoout.close();
}
}
if (obj.size() == 0 || promoTourCount == 0) {
promoPlistPath.delete();
promoCountFile.delete();
}
} catch (Exception e) {
e.printStackTrace();
}
}
Here it is giving me concurrent modification exception while the for loop iterates for the 2nd time or after that.
I am trying to update the value of promoTourCount in file each time as the loop iterates. But I am failing to do it. Because to avoid adding up multiple objects I am removing the object present at position 0 and adding the new one to that position( promoobj.remove(0);)
Plz help me

You are modifying the collection you are iterating on. This will trigger an error. You iterate over obj here:
for (HashMap<String, Object> tmpObj : obj) {
But remove from it here:
obj.remove(tmpObj);
I recommend you to store the items to remove in another collection and remove them from the map only when you finish the for loop.
Edit: << Adding example code >>
List<Integer> toRemove = new LinkedList<Integer>();
for (int i = 0; i < obj.size(); i++) {
HashMap<String, Object> tmpObj = obj.get(i);
if (/* something */) {
/* ... */
/* obj.remove(tmpObj); replaced with*/
toRemove.add(0, i); // notice that I add bigger indices first
}
}
// Here we make the removal from bigger indices to smaller ones
// Notice that we iterate and remove from different collections.
for (Integer indexToDelete : toRemove) {
obj.remove(indexToDelete);
}
This is the basic idea when you want to remove elements. However you need to output obj as modified immediately in the for loop. Then probably a bit of hacks with the indices will do better job for you:
for (int i = 0; i < obj.size(); i++) {
HashMap<String, Object> tmpObj = obj.get(i);
if (/* something */) {
/* ... */
/* obj.remove(tmpObj); replaced with*/
obj.remove(i); // We erase the element but this time we do not use enhanced for loop which is ok.
i--; // we decrease the index because th enumber of elements decreased. Index hack. Ugly.
System.out.println(obj); // modified obj :)
}
}

Related

Why do I get error "ArrayIndexOutOfBoundsException: length=0; index=0"?

My code:
private Collection<Film> getFilms() {
File files = new File(pathname);
File[] filesList = files.listFiles();
List<Film> list = Arrays.asList();
Log.d("filesList.length ", ""+filesList.length);
for (int i = 0; i < filesList.length; i++) {
try {
Film filmTemp = new Film(filesList[i]);
list.set(i, filmTemp);
} catch (Throwable e) {
Log.d("Error!", "Kobzda", e);
}
}
return list;
}
And I always get the same errors:
java.lang.ArrayIndexOutOfBoundsException: length=0; index=0
java.lang.ArrayIndexOutOfBoundsException: length=0; index=1
You are calling Arrays.asList() with no params which means the list you are creating is immutable (cannot add or remove elements) and empty.
Even if the List was mutable (say, by doing List<Film> list = new ArrayList<>()) you'd still run into an issue because you can't call set on a non-existent element index. In other words, an element has to already exist at that index in the List in order to successfully call set.
Instead, you should create a mutable List and call add.
Something like:
private Collection<Film> getFilms() {
File files = new File(pathname);
File[] filesList = files.listFiles();
List<Film> list = new ArrayList<>();
Log.d("filesList.length ", ""+filesList.length);
for (int i = 0; i < filesList.length; i++) {
try {
Film filmTemp = new Film(filesList[i]);
list.add(filmTemp);
} catch (Throwable e) {
Log.d("Error!", "Kobzda", e);
}
}
return list;
}
If you take a look at the docs for List#set
Replaces the element at the specified position in this list with the specified element.
Throws: ...
IndexOutOfBoundsException - if the index is out of range (index < 0 || index >= size())
(Emphasis added.)
So this method doesn't add a new element at the given index, it replaces an element that must already be there. But when you instantiated the list using Arrays.asList(), you created an empty list. Since there's no element at index 0, you can't replace one there.
You should create the list using new ArrayList<>(), and then use List#add (Arrays.asList() returns a List that can't add elements to new indices; its size is fixed).

Android: Set edittext with arraylistvalue

Hi i am converting from kilo to stone-pounds, i want to place stones in one edittext and pounds in one edittext , below is my method
public ArrayList<HashMap<String, Integer>> kiloTostomepound(int s) {
int stone = (int) (s * 2.2);
int stonevalue = stone/14;
int spound = (stone % 14);
arrayList = new ArrayList<HashMap<String,Integer>>();
HashMap<String, Integer> h1 = new HashMap<String, Integer>();
h1.put(STONE,stonevalue);
h1.put(STONEPOUND, spound);
arrayList.add(h1);
return arrayList;
}
i want to get values from the arryalist and set it to edittext.
Doing a below but givinf nullpointerexception
edt2.setText(String.valueOf(kiloTostomepound(arrayList.get(0).get(STONE))));
edt3.setText(String.valueOf(kiloTostomepound(arrayList.get(1).get(STONEPOUND))));
The below code traverses through the list and prints key and value.
for (int a =0; a<myList.size();a++)
{
HashMap<String, Integer> tmpData = (HashMap<String, Integer>) myList.get(a);
Set<String> key = tmpData.keySet();
Iterator it = key.iterator();
while (it.hasNext()) {
String hmKey = (String)it.next();
Integer hmData = (Integer) tmpData.get(hmKey);
System.out.println("Key: "+hmKey +" & Data: "+hmData);
it.remove(); // avoids a ConcurrentModificationException
}
}
So if you need the first value try following.
HashMap<String, Integer> tmpData = (HashMap<String, Integer>) myList.get(0);
Set<String> key = tmpData.keySet();
Iterator it = key.iterator();
// Get the first element
String hmKey = (String)it.next();
Integer hmData = (Integer) tmpData.get(hmKey);
// Set the key and value to Edit text
edt2.setText(hmKey+" "+hmData);
Seems like your assigning the value to the arrayList variable inside of the method. Hence the
kiloTostomepound(arrayList.get(0).get(STONE))
Will throw a nullpointer for arrayList.
If I understand your code correctly, the below code should do the trick. But I don't know the input for the kiloTostomepound method.
edt2.setText(String.valueOf(kiloTostomepound("INPUT TO METHOD").get(0).get(STONE)));
edt3.setText(String.valueOf(kiloTostomepound("INPUT TO METHOD").get(1).get(STONEPOUND)));
This is because your method returns the arrayList with the hashmaps inside.

Is it there a better way to Search HashMap from ArrayList

I am trying to implement Searching in ListView. My ListView is comprised of HashMap in ArrayList and I managed to implement the logic but I guess there is much object and memory allocation in my approach each time the text change. Therefore I am looking for less memory allocated logic to search in my ListView with HashMap in ArrayList
#Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
//textlength = searchBar.getText().length();
//text_sort.clear();
sortedArrayList.clear();
for (int i = 0; i < myHistList.size(); i++) {
HashMap<String, String> hash = new HashMap<String, String>();
hash = myHistList.get(i);
if (hash.get("myName").toLowerCase().indexOf(searchBar.getText().toString().toLowerCase()) != -1) {
String callerNum1 = hash.get("myNumber");
String myName1 = hash.get("myName");
HashMap<String, String> searchedHash = new HashMap<String, String>();
// adding each child node to HashMap key => value
searchedHash.put("myNumber", callerNum1);
searchedHash.put("myName", myName1);
recordingFile1);
// adding HashList to ArrayList
sortedArrayList.add(searchedHash);
}
}
ListView actualLv = mPullRefreshListView.getRefreshableView();
actualLv.setAdapter(new myHistoryListAdapter(myHistory.this, sortedArrayList));
}
At first you can replace
HashMap<String, String> hash = new HashMap<String, String>();
hash = myHistList.get(i);
with just
HashMap<String, String> hash = myHistList.get(i);
It will slightly reduce the number of redundant objects.
At second step if you need to compare strings are the same but ignore letters' case you can try to simplify your if condition
if (hash.get("myName").toLowerCase().indexOf(searchBar.getText().toString().toLowerCase()) != -1)
with
if(hash.get("myName").compareToIgnoreCase(searchBar.getText().toString()) == 0)
Also if you put the String callerNum1 = hash.get("myNumber"); above the if statement then you can save some time because you don't need to look through your HashSet two times to search the same element. It will look like following:
String callerNum1 = hash.get("myNumber");
if(callerNum1.compareToIgnoreCase(searchBar.getText().toString()) == 0){
...
}

parse json file from SD card in android app

I have an array of JSON objects on an SD card.
I get the file contents like this:
File yourFile = new File("/mnt/extSdCard/test.json");
FileInputStream stream = new FileInputStream(yourFile);
String jString = null;
try {
FileChannel fc = stream.getChannel();
MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
/* Instead of using default, pass in a decoder. */
jString = Charset.defaultCharset().decode(bb).toString();
}
finally {
stream.close();
}
The structure is like this:
[{"name":"john"},{"name":"fred"},{"name":"sam"}]
and I want to be able to parse them to make a listView. In JavaScript I can get them as an AJAX request and then do
var people = JSON.parse(data.responseText);
and then loop through the array. But I am a complete novice at java - I have found example code that does each of those things separately but I can't put them all together. Any help much appreciated.
The problem is that the above JSON structure represents a JSONArray and not a JSONObject
JSON Syntax
So after getting your jstring just do this
JSONArray array = new JSONArray(jString);
for(int i=0; i< array.length(); i++){
JSONObject obj = array.getJSONObject(i);
String value = obj.getString("name");
}
If you have it as a string, you should be able to parse it to a JSONObject with something like this:
JSONObject jObj = null;
// try parse the string to a JSON object
try {
jObj = new JSONObject(json);
Log.i(TAG, "JSON Data Parsed: " + jObj.toString());
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
I would also put the data (in your example) into an array, so it appears as something like:
{"names": [{"name": "john"},{"name": "fred"},{"name": "sam"}]}
And then to read your object again, you can put it into an array (or something else I guess) with something like this:
// create an empty list
ArrayList<String> l = new ArrayList<String>();
// pull the array with the key 'names'
JSONArray array = jObj.getJSONArray("names");
// loop through the new array
for(int i = 0; i < array.length(); i++){
// pull a value from the array based on the key 'name'
l.add(array.getJSONObject(i).getString("name"));
}
Hope at least some of this helps out (or at least points you in the correct direction). There are PLENTY of resources on here though, too.
EDIT:
Read up on JSON formatting. [] denotes array and {} denotes object, so you have an array of objects. That is why I recommended changing your format. If you are set on your format, either go with what Mr.Me posted for his answer, or just split your string at special characters and put them into an array that way.
Try this
String[] from = new String[] {"name"};
int[] to = new int[] { R.id.name};
List<HashMap<String, String>> fillMaps = new ArrayList<HashMap<String, String>>();
try
{
JSONArray names = new JSONArray(jsonString);
Log.i("MyList","Number of names " + names.length());
for (int j = 0; j < names.length(); j++)
{
JSONObject jsonObject = names.getJSONObject(j);
HashMap<String, String> map = new HashMap<String, String>();
map.put("name", jsonObject.getString("name"));
fillMaps.add(map);
}
}
catch (Exception e)
{
e.printStackTrace();
}
SimpleAdapter adapter = new SimpleAdapter(context, fillMaps, R.layout.result, from, to);
mListView.setAdapter(adapter);
Here mListView is your predefined ListView.
Feel free to share your doubts here, if any.

JSON can't read, key reading fail maybe

I wonder why I can't read the JSON Object like this :
{
"1":{"bulan":"Januari","tahun":"2012","tagihan":"205000","status":"Lunas"},
"2":{"bulan":"Februari","tahun":"2012","tagihan":"180000","status":"Lunas"},
"3":{"bulan":"Maret","tahun":"2012","tagihan":"120000","status":"Lunas"},
"4":{"bulan":"April","tahun":"2012","tagihan":"230000","status":"Lunas"},
"5":{"bulan":"Mei","tahun":"2012","tagihan":"160000","status":"Lunas"},
"6":{"bulan":"Juni","tahun":"2012","tagihan":"150000","status":"Belum Lunas"},
"panjang":6
}
with my android code like this :
try {
int length = jobj.getInt("panjang");
for(int n = 0; n < length; n++){
String m = Integer.toString(n)
JSONObject row = jobj.getJSONObject(m);
String bulan = row.getString("bulan");
String tahun = row.getString("tahun");
String tagihan = row.getString("tagihan");
String status = row.getString("status");
HashMap<String, String> map = new HashMap<String, String>();
map.put("bulan", bulan);
map.put("tahun", tahun);
map.put("tagihan", tagihan);
map.put("status", status);
list.add(map);
}
} catch (JSONException e) {
e.printStackTrace();
}
It always return nothing, but it works fine if I change the key m to specific key like if
String m = "1";
and I can't use
JSONObject row = jobj.getJSONObject(n);
because getJSONObject() just accept string, not int.
is there something wrong with my code?
Your problem lies in the initial iterator value. It failed to search for key "0", because you don't have "0". Change it to:
for(int n = 1; n <= length; n++){
Should fix the problem.

Categories

Resources