Hi I am new to programming.I am trying to create a android project like contanct list.I am generating data for the adapter class. I am getting IndexOutOfBoundsException. I know this is basic of java but I am unable to figure it out why i am getting this error. Thanks in advance.
Here is my code:
// How i am setting adapter from activity
customAdapter = new CustomAdapter(getActivity(), getDataSetForPojo(), mSectionsForPojo, mMapIndexForPojo);
mRecyclerView.setAdapter(customAdapter);
// Getting List for the adapter
private ArrayList<Pojo> getDataSetForPojo() {
List<Pojo> pojoList = genData();
getListIndexedForPojo(pojoList);
ArrayList results = new ArrayList<>();
ElementList obj;
int section = 0;
int normal = 0;
String str;
String ch;
int total = pojoList.size() + mSectionsForPojo.length;
for (int index = 0; index < total; index++) {
str = pojoList.get(normal).getStr(); //here I am getting error
ch = str.substring(0, 1);
if (index == 0 || ch.equals(mSectionsForPojo[section])) {
obj = new ElementList(ch, true);
mMapIndexForPojo.put(ch, index);
if (section < mSectionsForPojo.length - 1) {
section++;
} else {
section = 0;
}
} else {
obj = new ElementList(pojoList.get(normal).getStr(), false);
normal++;
}
results.add(index, obj);
}
return results;
}
// Generating list for the section
public void getListIndexedForPojo(List<Pojo> fruitList) {
mMapIndexForPojo = new LinkedHashMap<>();
for (int x = 0; x < fruitList.size(); x++) {
String str = fruitList.get(x).getStr();
String ch = str.substring(0, 1);
ch = ch.toUpperCase(Locale.US);
// HashMap will prevent duplicates
mMapIndexForPojo.put(ch, x);
}
Set<String> sectionLetters = mMapIndexForPojo.keySet();
// create a list from the set to sort
ArrayList<String> sectionList = new ArrayList<>(sectionLetters);
Collections.sort(sectionList);
mSectionsForPojo = new String[sectionList.size()];
sectionList.toArray(mSectionsForPojo);
}
// Generating DATA
private List<Pojo> genData() {
List<Pojo> pojoList = new ArrayList<>();
Pojo pojo;
pojo = new Pojo();
pojo.setId(1);
pojo.setStr("aback");
pojoList.add(pojo);
// adding more objects to list.
return pojoList;
}
I think the problem is your for loop in method "getDataSetForPojo()" is running more than the size of pojoList.
private ArrayList<Pojo> getDataSetForPojo() {
...
List<Pojo> pojoList = genData();
...
// total can have larger value than pojoList.size() if mSectionsForPojo.length isn't zero.
int total = pojoList.size() + mSectionsForPojo.length;
for (int index = 0; index < total; index++) {
str = pojoList.get(normal).getStr(); //here I am getting error
if (index == 0 || ch.equals(mSectionsForPojo[section])) {
} else {
...
normal++;
}
}
return results;
}
So it is possible that normal can be incremented more than pojoList size.
Related
I have been given a task to write my own implementation for removing duplicate objects from an array. The array is unsorted.
As an example, I have this array of objects
ItemsList[] objects = {
new ItemsList("ob1"),
new ItemsList("ob2"),
new ItemsList("ob2"),
new ItemsList("ob1"),
new ItemsList("ob3")
};
"ob1" stands for itemId
My goal is to get the result array like this ["ob1", "ob2", "ob3"], but given NullPointerException when trying to find objects that aren't doubled and add those to array.
Note: cannot use Set, HashSet, ArrayList, Arrays.copyOf, Sort etc. or any other tools such as iterators.
So far I've done this:
public String[] removeDuplicates(ItemsList[] objects) {
String[] noDubs = new String[objects.length];
int len = objects.length;
int pos = 0;
for (int i = 0; i < len; i++) {
for (int j = i + 1; j < len; j++) {
if (objects[i].getItemId().equals(objects[j].getItemId())) {
noDubs[pos] = objects[i].getItemId();
pos++;
}
else {
//NullPointerException given
if (!objects[i].getItemId().equals(objects[j].getItemId()) && !objects[i].getItemId().contains(noDubs[i])) {
noDubs[pos] = objects[i].getItemId();
pos++;
}
}
}
}
String[] result = new String[pos];
for(int k = 0; k < pos; k++) {
result[k] = noDubs[k];
}
return result;
}
getItemId is class ItemsList method
Here is another option. This copies entries to a buffer the first time it finds them, and then copies the buffer to a correctly sized array.
There is an advantage to looking for duplicates in the buffer, instead of the original array. If there are a lot of duplicates, then there will be fewer checks when looking in the buffer compared to when looking in the original array.
I pulled out the loop to check if an item is in the buffer into another function. This avoids nesting the for loops, which can make it easier to read.
I think this overall approach also reduces the number of variables required to keep track, which also helps make it easier to read.
private static ItemsList[] removeDuplicates(ItemsList[] arr) {
ItemsList[] buffer = new ItemsList[arr.length];
int bufferLength = 0;
for (ItemsList candidate : arr) {
if (!isInBuffer(candidate, buffer, bufferLength)) {
buffer[bufferLength] = candidate;
bufferLength++;
}
}
ItemsList[] result = new ItemsList[bufferLength];
for (int i = 0; i < bufferLength; i++) {
result[i] = buffer[i];
}
return result;
}
private static boolean isInBuffer(ItemsList candidate, ItemsList[] buffer, int bufferLength) {
for(int i = 0; i < bufferLength; i++) {
if (Objects.equals(candidate, buffer[i])) {
return true;
}
}
return false;
}
Here is an implementation. Just mark the item as duplicated if it is equal to one of the next elements. Later add it to the output array, which will need to grow.
public String[] removeDuplicates(ItemList[] items) {
String[] output = {};
for (int i = 0; i < items.length; i++) {
boolean isDuplicated = false;
ItemList current = items[i];
if (current == null)
throw new RuntimeException("item can not be null");
for (int j = i + 1; j < items.length; j++) {
if (current.equals(items[j])) {
isDuplicated = true;
break;
}
}
if (!isDuplicated) {
String[] temp = new String[output.length + 1];
System.arraycopy(output, 0, temp, 0, output.length);
temp[output.length] = current.getItemId();
output = temp;
}
}
return output;
}
You could also make every duplicate null and later add each non null element to the output array, like this:
public String[] removeDuplicates2(ItemList[] items) {
String[] temp = new String[items.length];
int inTemp = 0;
for (ItemList item : items) {
boolean isDuplicated = false;
if (item == null)
throw new RuntimeException("item can not be null");
for (int i = 0; i < inTemp; i++) {
if (item.getItemId().equals(temp[i])) {
isDuplicated = true;
break;
}
}
if (!isDuplicated) temp[inTemp++] = item.getItemId();
}
String[] output = new String[inTemp];
System.arraycopy(temp, 0, output, 0, inTemp);
return output;
}
But note that the first solution is faster
It would be better to use an intermediate array of booleans to track the duplicates and define the length of the result array. This would facilitate detection of multiple duplicates when the same element might occur more than 2 times.
Also, we need to make sure the method equals (and possibly hashCode) is properly overridden in ItemList:
// class ItemList
public boolean equals(Object o) {
if (null == o || !(o instanceof ItemList)) {
return false;
}
if (o == this) return true;
ItemList that = (ItemList) o;
return Objects.equals(this.itemId, that.itemId);
}
public int hashCode() {
return Objects.hash(this.itemId);
}
When checking for equality of ItemList it may be better to use Objects.equals to handle null values without throwing a NullPointerException. Thus, duplicate null entries in the input items will be filtered out too.
public static String[] removeDuplicates(ItemList[] items) {
final int n = items.length;
if (n < 1) {
return new String[0];
}
boolean[] dups = new boolean[n];
int dupCount = 0;
for (int i = 0; i < n; i++) {
ItemList current = items[i];
for (int j = i + 1; j < n; j++) {
if (dups[j]) {
continue;
}
if (Objects.equals(current, items[j])) {
dups[j] = true;
dupCount++;
}
}
}
String[] output = new String[n - dupCount];
for (int i = 0, j = 0; i < n; i++) {
if (!dups[i]) {
output[j++] = null == items[i] ? "<NULL>" : items[i].getItemId();
}
}
// info message
System.out.printf("Found and removed %d duplicate value%s%n", dupCount, dupCount != 1 ? "s" : "");
return output;
}
Test:
ItemList[] items = {
null, new ItemList("ob1"), new ItemList("ob2"), new ItemList("ob2"), new ItemList("ob1"),
new ItemList("ob3"), null, new ItemList("ob3"), new ItemList(null), new ItemList("ob5"),
new ItemList("ob2"), new ItemList(null), new ItemList("ob4"), new ItemList("ob5"), null,
};
System.out.println(Arrays.toString(removeDuplicates(items)));
// compare removal of duplicates to using set
System.out.println("\nUsing Set");
Set<ItemList> set = new LinkedHashSet<>(Arrays.asList(items));
System.out.println(set);
Output:
Found and removed 8 duplicate values
[<NULL>, ob1, ob2, ob3, null, ob5, ob4]
Using Set
[null, {id=ob1}, {id=ob2}, {id=ob3}, {id=null}, {id=ob5}, {id=ob4}]
I have a input string like
{{1,2},{3,4},{5,6}}.
I want to read the numbers into an two dimensional array like
int[][] arr = {{1,2},{3,4},{5,6}}.
Is there a good way to convert this string into int[][] ? Thanks.
The basic idea is as follows, you will have to add error handling code and more logical calculation of array size yourself. I just wanted to display how to split the string and make int [][]array.
String test = "{{1,2},{3,4},{5,6}}";
test = test.replace("{", "");
test = test.replace("}", "");
String []nums = test.split(",");
int numIter = 0;
int outerlength = nums.length/2;
int [][]array = new int[outerlength][];
for(int i=0; i<outerlength; i++){
array[i] = new int[2];
for(int j=0;j<2;j++){
array[i][j] = Integer.parseInt(nums[numIter++]);
}
}
hope it helps!
I'd go for solution using dynamic storage such as List from Collections, and then convert this to fixed primitive array at the end.
public static void main(String[] args) throws Exception {
System.out.println(Arrays.deepToString(parse("{{1,2},{3,4},{5,6}}")));
}
private static int[][] parse(String input) {
List<List<Integer>> output = new ArrayList<>();
List<Integer> destination = null;
Pattern pattern = Pattern.compile("[0-9]+|\\{|\\}");
Matcher matcher = pattern.matcher(input);
int level = 0;
while (matcher.find()) {
String token = matcher.group();
if ("{".equals(token)) {
if (level == 1) {
destination = new ArrayList<Integer>();
output.add(destination);
}
level++;
} else if ("}".equals(token)) {
level--;
} else {
destination.add(Integer.parseInt(token));
}
}
int[][] array = new int[output.size()][];
for (int i = 0; i < output.size(); i++) {
List<Integer> each = output.get(i);
array[i] = new int[each.size()];
for (int k = 0; k < each.size(); k++) {
array[i][k] = each.get(k);
}
}
return array;
}
Another alternative would be translate { to [ and } to ], then you have JSON, just use your favourite JSON parser, here I used GSON.
private static int[][] parse(String string) {
JsonElement element = new JsonParser().parse(string.replace("{", "[").replace("}", "]"));
JsonArray obj = element.getAsJsonArray();
int [][] output = new int[obj.size()][];
for (int i = 0; i < obj.size(); i++) {
JsonArray each = obj.get(i).getAsJsonArray();
output[i] = new int[each.size()];
for (int k = 0; k < each.size(); k++) {
output[i][k] = each.get(k).getAsInt();
}
}
return output;
}
New to java programming and I am currently trying to create a class similar to ArrayList using Arrays.
Am trying to add elements to an array and expand the array by copying them to a new array of bigger size.
I am getting an out of index error at 20.
Code may be messy but currently really stuck.
public class MyArrayList{
private String[] strings;
private int arraySize;
private int storedStrings;
public MyArrayList(int arraySize){
this.arraySize = arraySize;
this.strings = new String[arraySize];
}
public void addString(String string){
storedStrings = 0;
for (int i = 0; i < this.arraySize;i ++){
if (strings[i] != null){
storedStrings = storedStrings +1;
}
}
if (storedStrings == this.arraySize){
String[] newArray = new String[this.arraySize+10];
for (int i = 0; i < this.strings.length; i++){
strings[i] = newArray[i];
}
this.strings = newArray;
newArray[storedStrings] = string;
this.arraySize = this.arraySize +10;
}
else{
strings[storedStrings] = string;
}
for(int i = 0; i < strings.length; i++)
{
//System.out.println(strings[i]);
}
}
}
The code is being run in the test class where the error is being generated on line 10 of test class and line 47 of MyArrayList class.
This is the test code
public class TestArrayList{
public static void main(String[] args)
{
MyArrayList a = new MyArrayList(10);
for (int i = 0; i <50; i++){
a.addString("Test" + i);
}
for (int i = 0; i<50;i++){
System.out.println(a.getString(i*5));
}
}
}
you can do it like this:
public void addString(String string){
if (storedStrings == this.arraySize){
this.arraySize += 10;
String[] newArray = new String[this.arraySize];
for (int i = 0; i < this.storedStrings; i++){
newArray[i] = strings[i];
}
this.strings = newArray;
}
if (strings[storedStrings] == null){
strings[storedStrings++] = string;
}
// remove this loop it will show repeating values otherwise
for(int i = 0; i < storedStrings; i++)
{
System.out.println(strings[i]);
}
}
edit: as you are new to java always think about how can you do more with less code, how to avoid repetition of code, how to merge things that do common task. That will help you write better code
edit2 : the problem is with this loop
for (int i = 0; i<50;i++){
System.out.println(a.getString(i*5));
}
if you have 50 elements in array the getString method on (eg) i = 25 will be 25*5 = 125 which is not the index in the array that's why you are getting ArrayIndexOutOfBound Exception.
you can add
public int size(){
return storedStrings;
}
to check the size of your list which is the maximum item that is inside the list
First with your code there is a mistake in this line
strings[i] = newArray[i];
because you arenĀ“t copying the old data to new array but cleaning the strings array, I suppose that you wish do the contrary action.
In other hand you have extra code that you could improve.
public class MyArrayList{
private String[] strings;
private int arraySize;
public MyArrayList(int arraySize){
this.arraySize = arraySize;
this.strings = new String[arraySize];
}
public void addString(String string){
// Since you always do this
// it's better to use a local variale
int storedStrings = 0;
// Use the foreach syntax
// it's less prone to errors
// and easier to read
for (String s : this.strings){
if (s != null){
storedStrings++;
}else{
// since you want to count the strings in your array
// and you put them in this array
// one after the other
// no need to check the whole array
// when you find null you can exit the loop
break;
}
}
if (storedStrings == this.arraySize){
String[] newArray = new String[this.arraySize+10];
for (int i = 0; i < this.strings.length; i++){
// here we need to copy the content of strings in newArray
// NOT the other way
newArray[i] = this.strings[i];
}
this.strings = newArray;
newArray[storedStrings] = string;
this.arraySize += 10;
}else{
this.strings[storedStrings] = string;
}
}
public String[] getStrings(){
return this.strings;
}
}
As for the test class
public static void main(String[] args){
MyArrayList a = new MyArrayList(10);
for (int i = 0; i <50; i++){
a.addString("Test" + i);
}
for (String s : a.getStrings()){
System.out.println(a);
}
}
public boolean makeReservation(int id, AvilaNatalyPassenger request) {
boolean status = true;
ArrayList<Integer> inputValues = new ArrayList<Integer>();
for (int i = 0; i < 22; i++) {
for (int j = 0; j < 5; j++) {
id = seats[i][j];
if (id != -1) {
if (inputValues.contains(id)) {
status = false;
break;
}
else {
inputValues.add(id);
for(int a = 0; a < inputValues.size; a++)
seats[a] = inputValues[a];
}
}
}
}
return status;
}
This is what I have but its not correct. I need to add what I have in inputVaule arrayList into the array seats.
You can also look at the Java API: http://docs.oracle.com/javase/7/docs/api/index.html?java/util/ArrayList.html
public Object[] toArray()
Returns an array containing all of the elements in this list in proper sequence (from first to last element).
So this is what you could do:
seats[a] = inputValues.toArray();
Furthermore you cannot use inputValues[a] since it is not an array. What you probably could do is
seats[a] = (inputValues.toArray())[a];
To answer your question, here is an example:
ArrayList<String> stock_list = new ArrayList<String>();
stock_list.add("stock1");
stock_list.add("stock2");
String[] stockArr = new String[stock_list.size()];
stockArr = stock_list.toArray(stockArr);
for(String s : stockArr)
System.out.println(s);
Example is taken from here
If my sample data is a CSV file that looks like this:
a,,,b,
36,28,90,5,24
what would be the best way to either have something like
myStringArray = [a, [36,28,90]], [b, [5,24]]
or
myStringArray1 = {a,b}; // this part i can do
myStringArray2 = {{36,28,90}, {5,24}};
I am using Processing, which is based on Java, but my question is more about the general functionality of Java, so excuse my code formatting, if it doesn't appear java correct.
here is my import class:
class dTable {
int rowCount;
int columnCount;
String[][] data;
String filename;
dTable(String _filename) {
filename = _filename;
}
void load() {
String[] rows = loadStrings(filename);
String[] columns = split(rows[0], ',');
rowCount = rows.length;
columnCount = columns.length;
//set the size of the matrix
data = new String[rows.length][columns.length];
// add column pieces into data matrix
for (int i = 0; i < rows.length; i++) {
String[] colEntries = split(rows[i], ',');
for (int j = 0; j < columns.length; j++) {
data[i][j] = colEntries[j];
}
}
}
}
and here is my unworking attempts at a parsing class:
class dParse {
String[] bMaj;
String[][] bMin;
dParse() {
}
void getList(int integer) {
ArrayList dMaj = new ArrayList();
ArrayList dMin = new ArrayList();
String[][] minimums;
String[] _rowNameMaj = table.data[0]; //get data first to match
String[] _rowName = table.data[integer]; // get data to fill
//get first variables
for (int i = 0; i<_rowName.length; i++) { //iterate over
ArrayList tempMin = new ArrayList();
if (trim(_rowNameMaj[i]).length() != 0) {
dMaj.add(_rowNameMaj[i]);
}
}
//place maj values from arraylist into an array
String[] _bMaj = (String[]) dMaj.toArray(new String[0]);
bMaj = _bMaj; //set value to global variable
//min values
ArrayList bigOne = new ArrayList();
int count = 0;
for (int i = 0; i<_rowName.length; i++) { //iterate over
ArrayList tempMin = new ArrayList();
if (trim(_rowNameMaj[i]).length() != 0) { //check if box is not empty & set count to 0
//tempMin = dMaj.get(i); // set inner list
//println("maj " + count + " " + _rowNameMaj[i]);
tempMin.add(_rowName[i]);
count++;
//println("min" + count + " " + tempMin);
}
else if (trim(_rowNameMaj[i]).length() == 0) { //if next box is empty, add to count
count++;
tempMin.add(_rowName[i]);
//println("min" + count + " ");
}
minimums = new String[_bMaj.length][];
/various unworking attempts below
//place min values from arraylist into an array
//String[] temp_bMin = (String[]) tempMin.toArray(new String[0]);
//fl[] = append((new String(temp_bMin)), fl);
for (int n = 0; n< bMaj.lenth; n++ ) {
count[level]mums[n] = (String[]) toArray(new String[0]);
// println(minimums[n]);
// }
tempMin.clear(); //clear temporaryList
}
}
String[] getMaj() {
return bMaj;
}
String[][] getMin() {
return bMin;
}
}
Any help is appreciated,
Many thanks,
Dimitar
Dimitar... Perhaps a library such as Commons CSV or the links to the other libraries on that page would prove useful? However, if you insist on rolling your own CSV parser, look into the java.util.StringTokenizer class.
Pseudo code:
class Item {
String name;
List<String> values;
}
String[] names = line1.split(",");
String[] data = line2.split(",");
List<Item> items = new ArrayList<Item>();
Item curItem = null;
for (int i=0; i<data.length, i++)
{
if (names[i].isEmpty())
{
if (curItem == null) throw "first name is empty";
}
else
{
curItem = new Item();
items.add(curItem);
}
curItem.values.add(data[i]);
}
This uses an Item class to hold each item and a List<Item> for the whole thing. Downgrading to use nested arrays is left as an exercise.
Important If you need real CSV parsing (quoted fields, etc) you should use a CSV library to do the initial split and then apply the logic above to the results.