What is the relation between List and Array. Why i am getting ArrayIndexOutOfBoundsException.?
Basically i am passing one argument to a method, based on that using HQL, i am returning one set of ArrayList. Now my problem is that. when this ArrayList returns more than 0 (size) this is working exactly the way i want.
But when it returns 0 (size) ArrayList, i am getting Exception. why is that. can any body explain to me
Now i got one more doubt like if an arraylist returns 5(first) & 0(second as size i tested up to) i am not getting any Exception. but when it returns like 200 or more elements its getting exception. why is that? Is there any specific constant no. like up to this many elements array shouldn't give IndexOutofBounds and things like that? can any body explain to me?
here is my code:
public void setUpDisplay()
{
if (_flatView || _expired || _issue){ // these are all my views.
_deptBalances = fetchBalances(null);
}
else if (_searchGen.getGenericName() != null){
_storeGenList.clear();
_deptBalances = fetchBalances(_searchGen.getGenericName());
if (!ListUtil.nullOrEmptyList(_deptBalances)){
// i am displaying the result here.
}
else {
displaying error message.
}
}
// here i am using my _deptBalances to display(i am just putting this list into displaygroup).
}
// here is my method.
public List<DEPTStoreBalance> fetchBalances(String genName){
EntityManager em // Creating instance to entity manager.
List <DEPTStoreBalance> tempList = ListUtil.list();
String expClause = new String();
if (_expired){
expClause = "and gg.bSubjectToExpiration=true " +
"and msb.expirationDate <= :expDate ";
if(_expiringOnly){
expClause = expClause.concat(" and msb.expirationDate > :today");
}
else {
expClause = expClause +
"and (msb.expirationDate > :today " +
"or (balance.qtyBalance > 0 or balance.qtyInTransit > 0)) ";
}
}
else {
expClause = "and ((gg.bSubjectToExpiration=true " +
"and msb.expirationDate > :expDate) " +
"or gg.bSubjectToExpiration=false) ";
if (_flatView || _issue){
expClause = expClause.concat("and (balance.qtyBalance > 0 or balance.qtyInTransit > 0) ");
}
else if (genName != null){
expClause = expClause.concat("and gg.genericName = :genName ");
}
}
String hql = "select balance from DEPTStoreBalance as balance " +
" "+ // here are my joins with multiple tables.
"where dsg.store = :store " +
expClause;
if (_issue)
hql = hql.concat(" and dsi.deptIssue = :deptIssue");
Query q = em.createQuery(hql);
q.setParameter("store", _store); // here i am selecting the store(which is being changing in search component).
if (_issue)//Only saleable items should be issued
q.setParameter("expDate",12 months);
else
q.setParameter("expDate",_minExpDate ); // constant value :3
if (_expired)
q.setParameter("today", new Date());
if (genName != null){
q.setParameter("genName", genName);
}
if (_issue)
q.setParameter("deptIssue", true);
try{
tempList = (List <DEPTStoreBalance>) q.getResultList();
}
catch (NoResultException nre){
//do something
}
finally {
em.close();
}
return tempList;
}
Arraylist is a dynamic array. Array has fixed size where as Arraylist is not.
Example:
if you declare array as
int[] arr = new int[5];
you have to provide the size of an array.
ArrayList al = new ArrayList();
if(al.size()>0) {
// do your things
}
An ArrayList is nothing but a dynamically growing array.
You're experiencing an ArrayIndexOutofBoundException because when you receive an empty list and you're trying to access a particular location which is non-existent, JVM throws you an exception complaining that you've crossed the bound of the internal array a.k.a ArrayIndexOutOfBoundException.
For example, in your case, when you've an empty ArrayList, the size of the list would be 0. However if you try to access an index which is >= 0, JVM will throw an ArrayIndexOutofBoundException
ArrayList internally uses array to store its content. ArrayList is basically sort of dynamic array.
If you try to access an element at index which is not available, you will get ArrayIndexOutofBoundsException.
If your List has, say, 3 members and you are calling list.get(5) the exception is thrown. It is because the ArrayList is implemented by Java array.
Related
I am trying to populate an empty array in the first column with ordered numbers and write this back. This works, but I need the row location passed back too for reference in another method.
// Generate a customer/order number.
public static String[][] gen_cust_number(String[][] cust_order, int order_location)
{
for(int row = 0; row < cust_order.length; row++)
{
if (cust_order[row][0] == null)
{
cust_order[row][0] = Integer.toString(row + 1000);
order_location = row;
Gen.p("\n\n\tYour order number is : " + cust_order[row][0]);
break;
}
}
return cust_order;
}
I'm not very familiar with working with objects, pairs, and whatnot as I am still learning but have done some searching on it and am stumped in understanding how to do it.
I'm not 100% sure with what you're trying to achieve, but by reading the code I think what get_cust_number should do is
Generate new order to the very first empty order list.
Return the new order list and its index.
If this is right, you don't have to pass the String[][] back because the reference of this instance is what the caller side already know as it's passed in the parameters.
You can also remove the order_location param as it's never read inside the method.
So what you can do to make it work is to
Remove the order_location from params.
Return the index of added order instead of the array itself.
This results in the following code.
// Generate a customer/order number.
public static int gen_cust_number(String[][] cust_order)
{
for(int row = 0; row < cust_order.length; row++)
{
if (cust_order[row][0] == null)
{
cust_order[row][0] = Integer.toString(row + 1000);
Gen.p("\n\n\tYour order number is : " + cust_order[row][0]);
return row;
}
}
// cust_order is full
return -1;
}
In the calling side, you can do the following:
String[][] cust_order = /* Some orders according to your logic. */;
int cust_order_count = /* Number of the orders generated. */;
// Generate the order and this will be the new number of orders.
cust_order_count = gen_cust_number(cust_order);
RasEnumConnections function which realized in JNA is returning incomplete data.
What wrong? This is my code:
public static void main(String[] args) {
Connected();
}
private static void Connected () {
boolean state = false;
ArrayList<String> connectedNames = new ArrayList<>();
IntByReference lpcb = new IntByReference(0);
IntByReference lpcConnections = new IntByReference(0);
Rasapi32.INSTANCE.RasEnumConnections(null, lpcb,lpcConnections);
WinRas.RASCONN conn = new WinRas.RASCONN();
conn.dwSize = lpcb.getValue();
WinRas.RASCONN[] connArray;
if(lpcConnections.getValue() > 0)
connArray = (WinRas.RASCONN[])conn.toArray(lpcConnections.getValue());
else
connArray = (WinRas.RASCONN[])conn.toArray(1);
System.out.println("lpcb: " + lpcb.getValue() + " lpcConnections: " + lpcConnections.getValue() + " RASCONN Size: " + conn.dwSize);
int error = Rasapi32.INSTANCE.RasEnumConnections(connArray, lpcb,lpcConnections);
if(error == WinError.ERROR_SUCCESS) {
System.out.println("Entry name: " + Native.toString(connArray[0].szEntryName)
+ " Guid string: " + connArray[0].guidEntry.toGuidString());
System.out.println(connArray[0].guidEntry.Data1);
System.out.println(connArray[0].guidEntry.Data2);
System.out.println(connArray[0].guidEntry.Data3);
}
else System.out.println("Error: " + error);
WinRas.RASENTRY.ByReference entry = getPhoneBookEntry("test1");
if(entry != null) {
System.out.println("test1 guid: "+ entry.guidId.toGuidString());
System.out.println(entry.guidId.Data1);
System.out.println(entry.guidId.Data2);
System.out.println(entry.guidId.Data3);
}
else System.out.println("Error: " + Native.getLastError());
}
}
Char array szEntryName contains only 3 last chars of connection name. (Connection name is "test1")
As I've noted in the comments, the debug output gives you a strong hint at what's happening. The missing "t" and "e" characters appear as 0x74 and 0x65 in the midst of what JNA expects to be a 64-bit pointer. The logical conclusion is that Windows is returning a 32-bit pointer followed by the string, 4 bytes earlier than JNA expected.
RasEnumConnections states a few things regarding the buffer you are passing as connArray:
On input, an application must set the dwSize member of the first
RASCONN structure in the buffer to sizeof(RASCONN) in order to
identify the version of the structure being passed.
In your sample code above you are leaving this value the same as the value from the initial return. This is specifying the "wrong" version of the structure. Instead, you should set the dwSize member to the size you want in your JNA structure:
conn.dwSize = conn.size();
Actually, the constructor for RASCONN sets this for you! So you actually don't have to do this. But in your code sample above, you are overwriting what was pre-set; just delete your conn.dwSize line.
Note that since you are now requesting a (4-bytes per array element) larger buffer by definining the structure size, you also need to pass the increased size in the (second) RasEnumConnections() call. It's set as the number of elements times the (smaller) structure size, but you should reset to the number of elements times the (larger) size like this:
lpcb.setValue(conn.size() * lpcConnections.getValue());
prior to fetching the full array. Otherwise you'll get the error 632 (Incorrect Structure Size).
For reference (or perhaps a suitable replacement for your own code), take a look at the code as implemented in the getRasConnection(String connName) method in JNA's Rasapi32Util.java class.
I have built a method which compares objects attributes with user input int. The method then adds all the objects to an array(the assignment demands it to be an Array and not ArrayList). After its added I have a foor-loop which prints out a list of Results for an athlete(in user input), it prints out all results from one category and then another and so forth..
I keep getting a NullPointerException error on the last line which is a System.out.println. I have searched for an answer for hours, and read the NullPointerException posts here but cannot find the issue or solve it.
for (int x = 0; x < category.size(); x++) {
Category c = categories.get(x);
System.out.println("Result in " + c.categoryName() + " for " + matchedAthlete.surName() + " "
+ matchedAthlete.lastName() + ": ");
for (int i = 0; i < individarrayresult.length; i++) {
Result res = individarrayresult[i];
if (res.nameOfCategory().equals(c.categoryName())) {
System.out.println(res.categoryResult());
}
}
}
So the last line of code ( System.out.println ) gets the NullPointerException, I am desperete for help. Below is the Array filled with results from only 1 Athlete.
Result[] individarrayresult = new Result[resultlist.size()];
for (int i = 0; i < resultlist.size(); i++) {
Result res = resultlist.get(i);
if (res.athleteStartNumber() == DSN) {
individarrayresult[i] = res;
}
}
If you have a NullPointerException on that row:
System.out.println(res.categoryResult());
The problem is in the method categoryResult because res is not null, otherwyse the previous test
if (res.nameOfCategory().equals(c.categoryName())) {
must throw the NullPointerException prior of the System.out.
So check the code of categoryResult() or post it.
Perhaps, as T.J. said, that the problem is not on that row but on the previous row and the NullPointerException is related to the value of res. Post the complete StackTrace and row lines of your code to be sure of that answer.
I think you're mistaken, I think you're getting the NPE one line earlier, on this line:
if (res.nameOfCategory().equals(c.categoryName())) {
And the reason you're getting it is there are nulls in your array, because of how you fill it:
Result[] individarrayresult = new Result[resultlist.size()];
for (int i = 0; i < resultlist.size(); i++) {
Result res = resultlist.get(i);
if (res.athleteStartNumber() == DSN) {
individarrayresult[i] = res;
}
}
If res.athleteStartNumber() == DSN is false, you never assign anything to individarrayresult[i], so that array entry keeps its null default.
How to fix it:
Build up a list of matching results:
List<> individResults = new Arraylist<Result>(resultlist.size());
for (int i = 0; i < resultlist.size(); i++) {
Result res = resultlist.get(i);
if (res.athleteStartNumber() == DSN) {
individResults.add(res);
}
}
...and then either use that list directly, or convert it to an array:
Result[] individarrayresult = individResults.toArray(new Result[individResults.size()]);
...and use the resulting array.
(You can also do the same with the nifty new streams stuff in the latest version of Java, but I'm not au fait with them...)
It's possible, of course, that you're getting the NPE on the line you said you are and that there are two problems, and it just happens you've been processing all DSN entries so far. If so, and you fix the other problem, the first time you have a non-DSN entry, you'll run into this problem unless it fix it as well.
I have a list of class type which holds value from object of class type in following way
public List<Vacc_vs6> refarray_vac1(String fdate,String ldate) throws SQLException, ParseException {
st_jsp.clear();
try {
con = getConnection();
stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);
String vs1 = "sql query";
stmt.executeQuery(vs1);
rs = stmt.getResultSet();
while (rs.next()) {
Vacc_vs6 ref = new Vacc_vs6();
ref.setLogtime(rs.getString(1));
ref.setBeam_current(rs.getString(2));
ref.setBeam_energy(rs.getString(3));
ref.setst4_vs6_bag1_rb(rs.getString(4));
ref.setst4_vs6_bag2_rb(rs.getString(5));
ref.setst4_vs6_bag3_rb(rs.getString(6));
ref.setst4_vs6_bag4_rb(rs.getString(7));
ref.setst4_vs6_bag5_rb(rs.getString(8));
ref.setst4_vs6_bag6_rb(rs.getString(9));
ref.setst4_vs6_bag7_rb(rs.getString(10));
ref.setst4_vs6_bag8_rb(rs.getString(11));
ref.setst4_vs6_bag9_rb(rs.getString(12));
st_jsp.add(ref);
}
} catch (Exception e) {
System.out.println("\nException in refarray_vac1 " + e);
}
return st_jsp;
}
st_jsp is the list.
Now I take another list of of class type and want to add values into it corresponding to every column of list st_jsp. I also want to add only those values in the second list which satisfy the given if condition otherwise go to else and put null at particular columns.
For this the code is-
List<Vacc_vs6> new_list=new ArrayList<Vacc_vs6>();
double is = 9.5;
double js = 10.5;
int no=0;
for (no=0;no<st_jsp.size();no++) {
String i= st_jsp.get(no).getBeam_current();
double im = Double.parseDouble(i) ;
if(im>is && im<js) {
new_list.addAll(st_jsp);
} else {
new_list.addAll(null);
}
is +=10;js +=10;
}
Problem-1--> how to add all the 12 columns corresponding to that index in new_list.addAll(???); Did I have to add column where I put ??
ref.setLogtime(rs.getString(1));
ref.setBeam_current(rs.getString(2));
Problem-2 for(no=0;no<st_jsp.size();no++) loop will go till the size of st_jsp but if I do so then all values of st_jsp list will not be displayed because of else condition as I have to add 0 or null to those rows which do not satisfy the above if condition. What to do for this?
1 Problem-1--> **how to add all the 12 columns corresponding to that index in new_list.addAll(???);**Did I have to add column where I put ??
To add only the object that satisfies your condition to the new list you should do:
if (im > is && im < js) {
new_list.add(st_jsp.get(no));
}
The method addAll() adds all elements from one collection into another. So, the way you are doing it, the first time your condition is satisfied you are adding every ref in st_jsp to new_list. And then you will keep re-adding the elements everytime new_list.addAll(st_jsp) is called. Using add() will add only the object you want.
2) Problem-2 for(no=0;no<st_jsp.size();no++) loop will go till the size of st_jsp but if I do so then all values of st_jsp list will not be displayed because of else condition as I ahve to add 0 or null to those rows whcih do not satisfy the above if condition.What to do for this
You are doing the same action in else that you are doing when the if condition is satisfied, that is, adding all elements from st_jsp to new_list:
if (im > is && im < js) {
new_list.addAll(st_jsp);
} else {
new_list.addAll(st_jsp);
}
This means that, after your loop, you will end with st_jsp.size() copies of st_jsp in new_list.
If you need to add an object containing null in all fields to new_list everytime an object does not satisfy your condition you first need to create this object, and then add it when the condition is not met. Also, if you need to test for each element in st_jsp if it satisfies the conditions for all values of is and js, you need to place another loop inside the for loop.
List<Vacc_vs6> new_list = new ArrayList<Vacc_vs6>();
for (int no=0; no < st_jsp.size(); no++) {
double is = 9.5;
double js = 10.5;
double im = Double.parseDouble(st_jsp.get(no).getBeam_current());
// flag to check if an element was added to new_list
boolean added = false;
while (is < 209.9 && js < 210.5) {
if (im > is && im < js) {
new_list.add(st_jsp.get(no));
added = true;
break;
}
is += 10;
js += 10;
}
if (!added) {
// If the element was not added, add an empty object,
// assuming that no field is set when creating the object.
new_list.add(new Vacc_vs6());
}
}
I currently have an ArrayList holding objects of a class I have created, I then parse through the ArrayList in a for loop searching and comparing some data from the ArrayList and some global variables that are loaded else where, however this ArrayList is constantly growing and will eventually have about 115 elements to it towards the end, which then takes a very long time to search through, the function that does this is also called once for every line I read from a text file and the text file will usually be around 400-500 lines long so as you can tell it is very slow process even when testing on small files. Is there a way to speed this up by maybe using another collection instead of an ArrayList, my reasoning for using the ArrayList is I have to know what index it is on when it finds a match.
Here is the class:
private ArrayList<PanelData> panelArray = new ArrayList<PanelData>(1);
public class PanelData {
String dev = "";
String inst = "";
double tempStart = 0.0;
double tempEnd = 0.0;
}
Function:
public void panelTimeHandler (double timeStart, double timeEnd) throws SQLException {
PanelData temps = new PanelData();
temps.dev = devIDStr;
temps.inst = instanceStr;
temps.tempStart = timeStart;
temps.tempEnd = timeEnd;
boolean flag = false;
if(!flag)
{
panelArray.add(temps);
flag = true;
}
for(int i = 0; i < panelArray.size(); ++i ) {
if(panelArray.get(i).dev.equals(devIDStr) && panelArray.get(i).inst.equals(instanceStr)) {
if(panelArray.get(i).tempStart <= timeStart && panelArray.get(i).tempEnd >= timeEnd ) {
//Do Nothing
}
else
{
temps.dev = devIDStr;
temps.inst = instanceStr;
temps.tempStart = timeStart;
temps.tempEnd = timeEnd;
insert();
panelArray.set(i, temps);
}
}
else
{
temps.dev = devIDStr;
temps.inst = instanceStr;
temps.tempStart = timeStart;
temps.tempEnd = timeEnd;
panelArray.add(temps);
insert();
}
}
}
If there is something more you would like to see just ask, thanks. Beef.
Update: Added insert() function
private void insert() throws SQLException
{
stmt = conn.createStatement();
String sqlStm = "update ARRAY_BAC_SCH_Schedule set SCHEDULE_TIME = {t '" + finalEnd + "'} WHERE SCHEDULE_TIME >= {t '" + finalStart + "'} AND" +
" SCHEDULE_TIME <= {t '" + finalEnd + "'} AND VALUE_ENUM = 0 AND DEV_ID = " + devIDStr + " and INSTANCE = " + instanceStr;
int updateSuccess = stmt.executeUpdate(sqlStm);
if (updateSuccess < 1)
{
sqlStm = "insert into ARRAY_BAC_SCH_Schedule (SITE_ID, DEV_ID, INSTANCE, DAY, SCHEDULE_TIME, VALUE_ENUM, Value_Type) " +
" values (1, " + devIDStr + ", " + instanceStr + ", " + day + ", {t '" + finalStart + "'}, 1, 'Unsupported')";
stmt.executeUpdate(sqlStm);
sqlStm = "insert into ARRAY_BAC_SCH_Schedule (SITE_ID, DEV_ID, INSTANCE, DAY, SCHEDULE_TIME, VALUE_ENUM, Value_Type) " +
" values (1," + devIDStr + ", " + instanceStr + ", " + day + ", {t '" + finalEnd + "'}, 0, 'Unsupported')";
stmt.executeUpdate(sqlStm);
}
if(stmt!=null)
stmt.close();
}
Update:
Thank you to Matteo, I realized I was adding to the array even if I didnt find a match till the 10th element it would then added to the array the first 9 times which created many extra elements in the array, which was why it was so slow, I added some breaks and did a little tweaking in the function, and it improved the performance a lot. Thanks for all the input
you can use LinkedHashSet. It seems you add only elements to the end of the list, which is exactly what LinkedHashSet does as well, when inserting an element.
Note however, a LinkedHashSet will not allow duplicates, since it is a set.
Searching if an element exists will be O(1) using contains()
Using the LinkedHashSet will also allow you to keep track of where an element was added, and iterating it will be in order of insertion.
What about using a hashmap?
I would create a small class for the key:
class Key {
String dev, instr;
// todo: implements equals & hashCode
}
and create the map:
Map<Key, PanelData> map = new HashMap...
then you can easily find the element you need by invoking map.get(new Key(...)).
Instead of creating a new class, you could also tweak the PanelData class, implementing methods equals & hashcode so that two classes are equal iff their dev and instr are equal. In this case, your map becomes:
Map<PanelData, PanelData> map ...
// to add:
map.put(temps, temps)
// to search:
PanelData elem = map.get(new PanelData(desiredDev, desiredInstr));
Quite a few optimiztions here.
1) the call: panelArray.get(i) is used repeatedly. Declare a PanelData variable outside the loop, but initialize it only once, at the very begining of the loop:
PanelData pd = null;
for (int i = 0; i < panelArray.size(); ++i) {
pd = panelArray.get(i);
...
}
2) If your dataset allows it, consider using a few maps to help speed look up times:
HashMap<String, PanelData> devToPanelDataMapping = new HashMap<String,PanelData>();
HashMap<String, PanelData> instToPanelDataMapping = new HashMap<String,PanelData>();
3) Consider hashing your strings into ints or longs since String.equals() is slow compared to (int == int)
4) If the ArrayList will be read only, perhaps a multithread solution may help. The thread that reads lines from the text file can hand out individual lines of data to different 'worker' threads.
1) Create PanelArray with the max expected size + 10% when you first create it.
List<PanelData> panelArray = new ArrayList<PanelData>(130) - this will prevent dynamic reallocations of the array which will save processing time.
2) What does insert() do? Odds are that is your resource hog.
This problem might best be solved with a different data structure such as a HashMap or SortedSet.
In order to use a HashMap, you would need to define a class that can produce a hash code for the dev and inst string pairs. One solution is something like:
public class DevAndInstPair
{
private String dev, inst;
#Override
public int hashCode() {
return ((dev.hashCode() * 0x490aac18) ^ inst.hashCode());
}
#Override
public boolean equals(Object o) {
if (o == null || !(o instanceof DevAndInstPair)) {
return false;
}
DevAndInstPair other = (DevAndInstPair) o;
return (dev.equals(other.dev) && inst.equals(other.inst));
}
}
You would then use HashMap<DevAndInstPair, PanelData> as the map type.
Alternatively, if you know that a certain character never appears in dev strings, then you can use that character as a delimiter separating the dev value from the inst value. Supposing that this character is a hyphen ('-'), the key values would be dest + '-' + inst and the key type of the map would be String.
To use SortedSet, you would either have PanelData implement Comparable<PanelData> or write a class implementing Comparator<PanelData>. Remember that the compare operation must be consistent with equals.
A SortedSet is somewhat trickier to use than a HashMap, but I personally think that it is the more elegant solution to this problem.