Android Text function forcecloses rand issue - android

after the previous fix i now have a new issue. Got advised to ask a new question, so here it is!
It still force closes, but now on a new line.
public void AI(String text) {
// initiate new lists to be on the safe side
List<String> indexer = new ArrayList<String>();
List<String> sentence = new ArrayList<String>();
List<String> explode = new ArrayList<String>();
List<String> ary = new ArrayList<String>();
explode = Arrays.asList(text.split(" "));
// initiate randint and trigger variable
Random rand = new Random();
int randint = rand.nextInt(explode.size());
// initiate the trigger variable
String trigger = explode.get(randint);
//check if word exists in database and add if it not.
int i = 0;
for(String word : explode) {
if(common.get(word) == null) {
words.add(word);
common.put(word, 1);
context.put(word, explode);
pos.put(word, i);
length.put(word, explode.size());
if(word.equals(trigger)) {
ary = new ArrayList<String>(explode);
}
}else{
common.put(word, common.get(word)+1 );
}
i++;
}
// fill the arraylist sentence with words to be used, some in context, some random from the database.
for(int i2 = 0; i2 < length.get(trigger); i2++ ) {
randint = rand.nextInt(length.get(trigger));
if(randint < length.get(trigger)/2) {
//
if(ary.get(i2)!=null) {
sentence.add(ary.get(i2));
}
}else{
sentence.add(words.get(rand.nextInt(words.size())));
}
}
// use to the pos-hashmap to check at which index the word was detected at, if not place it at the deliberate index.
for(int i3 = 0; i3 < sentence.size(); i3++) {
if(sentence.get(i3)!=null) {
indexer.add(pos.get(sentence.get(i3)), sentence.get(i3));
}
}
// compose the final string that is to be passed to the speak function
for(int i4 = 0; i4 < indexer.size(); i4++) {
say = say + indexer.get(i4)+" ";
}
// pass the string to the speak function
mTts.speak(say, TextToSpeech.QUEUE_FLUSH, null);
// removing final string to be ready for next iteration
say = "";
// end of AI stuff
}
Variables:
// arraylists
public List<String> explode = new ArrayList<String>();
public List<String> words = new ArrayList<String>();
public List<String> sentence = new ArrayList<String>();
public List<String> indexer = new ArrayList<String>();
// hashmaps
public Map<String, Integer> common = new HashMap<String, Integer>();
public Map<String, List<String>> context = new HashMap<String, List<String>>();
public Map<String, Integer> pos = new HashMap<String, Integer>();
public Map<String, Integer> length = new HashMap<String, Integer>();
//strings
public String say;
And logcat:
05-26 19:24:42.926: W/dalvikvm(543): threadid=3: thread exiting with uncaught exception (group=0x4001b188)
05-26 19:24:42.926: E/AndroidRuntime(543): Uncaught handler: thread main exiting due to uncaught exception
05-26 19:24:42.956: E/AndroidRuntime(543): java.lang.IndexOutOfBoundsException: Invalid location 0, size is 0
05-26 19:24:42.956: E/AndroidRuntime(543): at java.util.ArrayList.get(ArrayList.java:341)
05-26 19:24:42.956: E/AndroidRuntime(543): at sarah.namespace.SarahActivity.AI(SarahActivity.java:186)
Second logcat:
05-26 21:38:44.555: W/dalvikvm(571): threadid=3: thread exiting with uncaught exception (group=0x4001b188)
05-26 21:38:44.555: E/AndroidRuntime(571): Uncaught handler: thread main exiting due to uncaught exception
05-26 21:38:44.575: E/AndroidRuntime(571): java.lang.IndexOutOfBoundsException
05-26 21:38:44.575: E/AndroidRuntime(571): at java.util.ArrayList.add(ArrayList.java:145)
05-26 21:38:44.575: E/AndroidRuntime(571): at sarah.namespace.SarahActivity.AI(SarahActivity.java:188)
What the logcats are screaming at:
First:
sentence.add(words.get(rand.nextInt(words.size())));
Second:
for(int i3 = 0; i3 < sentence.size(); i3++) {
if(sentence.get(i3)!=null) {
indexer.add(pos.get(sentence.get(i3)), sentence.get(i3));
}
}
I would be very happy if someone could help me beat this riddle again!

Hmm, I am uncertain about which lines are 186 and 188 (the two that throw the OutOfBounds exceptions). But looking at this loop, I have some suggestions:
for(int i2 = 0; i2 < length.get(trigger); i2++ ) {
From above we notice that length.get(trigger) is always set to explode.size() and we can see that explode.size() never changes. We could check against explode.size() instead or use a for-each loop again. Carrying on:
randint = rand.nextInt(length.get(trigger));
if(randint < length.get(trigger)/2) {
This looks like you want a 50/50 chance of: adding the original word to sentence or
if(ary.get(i2)!=null) {
sentence.add(ary.get(i2));
}
}else{
sentence.add(words.get(rand.nextInt(words.size())));
}
}
... a random word to sentence.
Also I beleive this could throw an exception:
if(ary.get(i2)!=null) {
sentence.add(ary.get(i2));
because you are checking the validity of i2 against length.get(trigger) not ary.size(). Now remember that ary is simply a copy of explode.
So let's condense this loop to:
for(String word : explode) {
if(rand.nextInt(1)) // 50/50 chance of being false or true (0 or 1)
sentence.add(word);
else
sentence.add(words.get(rand.nextInt(words.size())));
}
Take a look at the remaining two loops, if you apply a similar for-each loop you will be able to condense and expedite these as well. I don't know the rest of the app's code, but you might be able to remove a few Lists and Maps entirely. Cheers!

Related

How can I create a group of months in expandable list view?

How can I create a group of months and add days to each of them in expandable list view? I try with for loop like this
private void prepareListData() {
months = new ArrayList<String>();
days= new HashMap<String, List<String>>();
daysArray = new ArrayList<String>();
Calendar currentDate = Calendar.getInstance();
for (int i = 50; i >= 0; i--) {
String a = MyChangeDateFomatter.getStringDateFormatMonth(currentDate
.getTimeInMillis());
currentDate.add(Calendar.DATE, -1);
if(months==null||(months.get(i).equalsIgnoreCase(months.get(i-1))==false)) {
months.add(a);
for (int j = 50; i >= 0; i--) {
if(months.get(i).equalsIgnoreCase(months.get(i-1))==true) {
String b = MyChangeDateFomatter.getStringDateFormatMonth(currentDate
.getTimeInMillis());
daysArray.add(b);
days.put(months.get(i),daysArray);
}
else {
days.put(months.get(i-1),daysArray);
}
}
}
}
}
error
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.testexpandablelistview/com.example.testexpandablelistview.CalendarActivity}:
java.lang.IndexOutOfBoundsException: Invalid index 50, size is 0
Please show me how to do that?
The reason why you are getting an IndexOutOfBoundsException is because you are trying to get an item at position 50 of your months list in your first if statment while the list had no members.
The following code should give you the correct months List and days Hash. (I haven't tested it though, so there could be some errors.)
String a = MyChangeDateFomatter.getStringDateFormatMonth(currentDate
.getTimeInMillis());
months.add(a);
daysArray.add(a);
// Removed one since it was added outside the loop
for (int i = 49; i >= 0; i--) {
currentDate.add(Calendar.DATE, -1);
a = MyChangeDateFomatter.getStringDateFormatMonth(currentDate
.getTimeInMillis());
// Checks if a is in the months List
if (!months.get(months.size() - 1).equals(a)) {
days.put(months.get(months.size() - 1), daysArray);
daysArray = new ArrayList<>();
months.add(a);
}
daysArray.add(a);
}
days.put(months.get(months.size() - 1), daysArray);

NullPointerException while using adapter.getItem(position)

I have the following code in WeekDays.java
ArrayAdapter<TaskInAWeek> adapter1 = (ArrayAdapter<TaskInAWeek>) getListAdapter() ;
TaskInAWeek taski;
ArrayList<Long> checkedItms = new ArrayList<Long>();
ArrayList<Long> uncheckedItms = new ArrayList<Long>();
for(int i=0;i<values.size();i++)
{
Log.i("value's size:" +values.size()," ");
if(EditStatusAdapter.tog==1)
{
Log.i("i::"+i," ");
taski = adapter1.getItem(i);
long id = taski.getId();
Log.i("nid:"+id," ");
checkedItms.add(id);
}
else
{
Log.i("i::"+i," ");
taski = adapter1.getItem(i);
long id = taski.getId();
Log.i("nid:"+id," ");
uncheckedItms.add(id);
}
}
Its custom Array Adapter is EditStatusAdapter.java. I get a NullPointerException at this pttaski = adapter1.getItem(i);.
I have used similar one in one of my activity but it did work fine. I guess its due to the custom array adapter. But I could not ignore it as well. Can anyone tel me how to clear the exception?

Strange java.lang.ArrayIndexOutOfBoundsException

I have a strange problem in my application
Some users send me the error:
java.lang.ArrayIndexOutOfBoundsException
i , myself , have never experienced that error. Here is the code:
for(int i =0; i<length*2; i+=2) {
if(charsLeft[i/2]==1)
temp[i]=word[i/2];//IT HAPPENS HERE
....
length = word.length;
charsLeft = new int[length];
temp = new String[length*2];
When a users goes back to home screen , the application saves and later loads the data this way:
public Bundle saveState(Bundle bundle) {
synchronized (surfaceHolder) {
if (bundle != null) {
bundle.putStringArray("word",game.word.word);
bundle.putIntArray("charsLeft",game.word.charsLeft);
bundle.putInt("length",game.word.word().length());
bundle.putStringArray("temp",game.word.temp);
bundle.putCharArray("characters", game.word.characters);
...
}
}
return bundle;
}
public synchronized void restoreState(Bundle bundle) {
synchronized (surfaceHolder) {
mPaused = true;
if (bundle != null) {
game.word.word = bundle.getStringArray("word");
game.word.length = bundle.getInt("length");
game.word.init();
game.word.charsLeft = bundle.getIntArray("charsLeft");
game.word.temp = bundle.getStringArray("temp");
game.word.characters = bundle.getCharArray("characters");
...
}
}
}
Does anyone see where it goe
EDIT
full loop
for(int i =0; i<(length)*2; i+=2) {
if(charsLeft[i/2]==1)
temp[i]=word[i/2];
else
temp[i]="_";
temp[i+1]=" ";
}
Example word[0] = a word[1] = n .....
->"answer"
the loop diveds the word in spaces and the letter or if the letter isnt guessed yet by a _
ex. a n s _ e _
EDIT:
I think I found the error :
A thread was calling the loop while an other thread could reassign word to another value , and if the loop was called before the value of length was changed then you have an error.
I changed the loop to this
temp = new String[word.length*2];
for(int i =0; i<(word.length*2); i+=2) {
if(charsLeft[i/2]==1)
temp[i]=word[i/2];
Now lets hope its fixed
Forget your loop if all you want to do is divide the word by spaces or blanks. Just using split:
String[] words = word.split( "\s|_" );
That will spit the word into an array of words on either a space or an underscore.

Concurrent modification exception for list

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 :)
}
}

Array Being Overwritten with Last Index in Loop

I'm working on code that takes two arrays with strings (the strings are just sentences) and allocates them to classes which are held in another array (The Sentence class array shown below in the code).
So here's my problem. When popList() is called, the for loop runs through twice and works fine, putting the first index of addStrings and addTranslation into the first class in the array. However, when the loop indexes up and runs temp.sentence = addStrings[1] again, it OVERRIDES the first class's .sentence also. Then when temp.translations = addTranslations[1] runs again it OVERRIDES the first class's .translation.
So by the end of the loop, all of the arrays are filled with the same thing: the last index of addStrings and addTranslation. Every time it loops it overwrites all the indices before it with the index it's supposed to be putting in.
Anyone know what the problem is here? Thanks!
public class Sentence {
public String sentence;
public String translation;
Sentence() {
sentence = " ";
translation = " ";
}
}
private void popStrings() {
addStrings[0] = "我是你的朋友。"; addTranslations[0] = "I am your friend.";
addStrings[1] = "你可以帮助我吗?"; addTranslations[1] = "Could you help me?";
addStrings[2] = "我不想吃啊!"; addTranslations[2] = "I don't want to eat!";
}
//Fill Sentence array with string and translation arrays
private void popList() {
int i = 0;
Sentence temp = new Sentence();
for(i = 0; i < addStrings.length && i < addTranslations.length ; i++) {
temp.sentence = addStrings[i];
temp.translation = addTranslations[i];
sentences[i] = temp;
}
}
You need to create new Sentence() inside the loop:
for(i = 0; i < addStrings.length && i < addTranslations.length ; i++) {
Sentence temp = new Sentence();
temp.sentence = addStrings[i];
temp.translation = addTranslations[i];
sentences[i] = temp;
}
Otherwise you set sentence and translation continuously in the same object.

Categories

Resources