Java - outOfMemory - Heap Space - java
So I'm trying to complete an exercise where I've been asked to implement a method that does a binary search in an ArrayList of objects. From the exercise:
Binary search
In the Main-class, implement a method public static int binarySearch(ArrayList<Book> books, int searchedId), which searches the list it received as a parameter, for a book with an id variable that matches the value of searchedId variable it received as a parameter. If that book is found the method, should return the index it's located at, in the list it received as a parameter. If the book isn't found, the method should return the value -1.
The method must be implemented as a binary search, which assumes the list is ordered. You should also assume, that the ids towards the beginning of the list, are always smaller than the ids towards the end of the list.
I have created two methods, one to check whether the arraylist is sorted (isItSorted) and the other one that will perform the binary search if the aforementioned method evaluates to true (binarySearch). Please see below:
public static boolean isItSorted(ArrayList<Book> books) {
ArrayList<String> boo = new ArrayList<>();
String isItSorted = "";
for (int i = 0; i < books.size(); i++) {
for (int j = i + 1; j < books.size(); j++) {
if (books.get(i).getId() < books.get(j).getId()) {
isItSorted = "true";
boo.add(isItSorted);
} else {
isItSorted = "false";
boo.add(isItSorted);
}
}
}
if (!(boo.contains("false"))) {
return true;
}
return false;
}
public static int binarySearch(ArrayList<Book> books, long searchedId) {
if (searchedId < 0 || books.isEmpty()) {
return -1;
} else if (isItSorted(books)) {
int start = 0;
int end = books.size() - 1;
int middle = (start + end) / 2;
if (books.get(middle).getId() == searchedId) {
return middle;
} else if (books.get(middle).getId() > searchedId) {
end = middle - 1;
} else if (books.get(middle).getId() < searchedId) {
start = middle + 1;
}
while (start <= end) {
if (books.get(start).getId() == searchedId) {
return start;
}
start++;
}
}
return -1;
}
Inside these java files, there's a test package that tests whether my solution is correct or not. While 95% of the tests are successful, when it reaches the method below (where it compares the time of execution compared to my other method (linear search)), I get the error Java outOfMemory heap Space.
I use NetBeans. I've already tried the JVM commands.
My solution seems to work with every number of objects I've tried, so perhaps there's something wrong with the test code below?
#Test
#Points("07-05.2")
public void binarySearchIsFasterThanLinearSearch() throws Throwable {
ArrayList<Book> books = generateBooks(10000);
Collections.sort(books, (k1, k2) -> k1.getId() - k2.getId());
int searched = 1000001;
long bSearchStart = System.nanoTime();
int binarySearchId = Searching.binarySearch(books, searched);
long bSearchEnd = System.nanoTime();
assertTrue("When binary search does not find what was searched for, it must return -1", binarySearchId == -1);
long lSearchStart = System.nanoTime();
int linearSearchId = Searching.linearSearch(books, searched);
long lSearchEnd = System.nanoTime();
assertTrue("When linear search does not find what was searched for, it must return -1", linearSearchId == -1);
long bSearchTime = bSearchEnd - bSearchStart;
long lSearchTime = lSearchEnd - lSearchStart;
assertTrue("When there are 10000 books to search, and the searched book is not found, binary search should be a lot faster than linear search. Current this isn't so", bSearchTime * 2 < lSearchTime);
}
ArrayList<String> boo = new ArrayList<>();
String isItSorted = "";
for (int i = 0; i < books.size(); i++) {
for (int j = i + 1; j < books.size(); j++) {
if (books.get(i).getId() < books.get(j).getId()) {
isItSorted = "true";
boo.add(isItSorted);
} else {
isItSorted = "false";
boo.add(isItSorted);
}
}
}
Adds on the order of 100 million items to the ArrayList boo.
If you want to check if something is sorted you can use much simpler code:
Book prev = books[0];
for (int i = 1; i < books.size(); i++) {
if (prev.getId() > books[i].getId())
return false;
}
return true;
But you shouldn't need to call it inside binarySearch() because that will defeat the purpose of binarySearch() and make it as slow as linearSearch().
Related
How to generate inner loops automatically in Java
I am trying to find a way to generate inner loops on demand (and have the depth as a variable). In the following example, I am trying to generate a list of references such as jobo.2.2.2.2.2.2 where each .2 is added in the inner loop. Here is what I have at the moment when I implement the new loop manually for 5 level of depth (i, j, k, l): public void buildTaskList(){ String jobName ="jobo"; String last=""; long max=3; List<String> tasks = new ArrayList<>(); for (long i = 1; i <= max; i++) { for (long j = 1; j <= max; j++) { if (j==max){ last="*"; tasks.add(jobName+"."+i+"."+j+last); }else { last=""; for (long k = 1; k <= max; k++) { if (k==max){ last="*"; tasks.add(jobName+"."+i+"."+j+"."+k+last); }else { last=""; for (long l = 1; l <= max; l++) { if (l==max){ last="*"; tasks.add(jobName+"."+i+"."+j+"."+k+"."+l+last); }else{ last=""; for (long m = 1; m <= max; m++) { if (m==max){ last="*"; tasks.add(jobName+"."+i+"."+j+"."+k+"."+l+"."+m+last); }else{ last=""; for (long n = 1; n <= max; n++) { if (n==max)last="*";else last=""; tasks.add(jobName+"."+i+"."+j+"."+k+"."+l+"."+m+"."+n+last); } } } } } } } } } } tasks.add(jobName+"."+(max+1)+last); System.out.println(tasks); } The result here is: jobo.1.1.1.1.1.1, jobo.1.1.1.1.1.2, jobo.1.1.1.1.1.3*, jobo.1.1.1.1.2.1, jobo.1.1.1.1.2.2, jobo.1.1.1.1.2.3*, jobo.1.1.1.1.3*, jobo.1.1.1.2.1.1, jobo.1.1.1.2.1.2, jobo.1.1.1.2.1.3*, jobo.1.1.1.2.2.1, jobo.1.1.1.2.2.2, jobo.1.1.1.2.2.3*, jobo.1.1.1.2.3*, jobo.1.1.1.3*, jobo.1.1.2.1.1.1, jobo.1.1.2.1.1.2, jobo.1.1.2.1.1.3*, jobo.1.1.2.1.2.1, jobo.1.1.2.1.2.2, jobo.1.1.2.1.2.3*, jobo.1.1.2.1.3*, jobo.1.1.2.2.1.1, jobo.1.1.2.2.1.2, jobo.1.1.2.2.1.3*, jobo.1.1.2.2.2.1, jobo.1.1.2.2.2.2, jobo.1.1.2.2.2.3*, jobo.1.1.2.2.3*, jobo.1.1.2.3*, jobo.1.1.3*, jobo.1.2.1.1.1.1, jobo.1.2.1.1.1.2, jobo.1.2.1.1.1.3*, jobo.1.2.1.1.2.1, jobo.1.2.1.1.2.2, jobo.1.2.1.1.2.3*, jobo.1.2.1.1.3*, jobo.1.2.1.2.1.1, jobo.1.2.1.2.1.2, jobo.1.2.1.2.1.3*, jobo.1.2.1.2.2.1, jobo.1.2.1.2.2.2, jobo.1.2.1.2.2.3*, jobo.1.2.1.2.3*, jobo.1.2.1.3*, jobo.1.2.2.1.1.1, jobo.1.2.2.1.1.2, jobo.1.2.2.1.1.3*, jobo.1.2.2.1.2.1, jobo.1.2.2.1.2.2, jobo.1.2.2.1.2.3*, jobo.1.2.2.1.3*, jobo.1.2.2.2.1.1, jobo.1.2.2.2.1.2, jobo.1.2.2.2.1.3*, jobo.1.2.2.2.2.1, jobo.1.2.2.2.2.2, jobo.1.2.2.2.2.3*, jobo.1.2.2.2.3*, jobo.1.2.2.3*, jobo.1.2.3*, jobo.1.3*, jobo.2.1.1.1.1.1, jobo.2.1.1.1.1.2, jobo.2.1.1.1.1.3*, jobo.2.1.1.1.2.1, jobo.2.1.1.1.2.2, jobo.2.1.1.1.2.3*, jobo.2.1.1.1.3*, jobo.2.1.1.2.1.1, jobo.2.1.1.2.1.2, jobo.2.1.1.2.1.3*, jobo.2.1.1.2.2.1, jobo.2.1.1.2.2.2, jobo.2.1.1.2.2.3*, jobo.2.1.1.2.3*, jobo.2.1.1.3*, jobo.2.1.2.1.1.1, jobo.2.1.2.1.1.2, jobo.2.1.2.1.1.3*, jobo.2.1.2.1.2.1, jobo.2.1.2.1.2.2, jobo.2.1.2.1.2.3*, jobo.2.1.2.1.3*, jobo.2.1.2.2.1.1, jobo.2.1.2.2.1.2, jobo.2.1.2.2.1.3*, jobo.2.1.2.2.2.1, jobo.2.1.2.2.2.2, jobo.2.1.2.2.2.3*, jobo.2.1.2.2.3*, jobo.2.1.2.3*, jobo.2.1.3*, jobo.2.2.1.1.1.1, jobo.2.2.1.1.1.2, jobo.2.2.1.1.1.3*, jobo.2.2.1.1.2.1, jobo.2.2.1.1.2.2, jobo.2.2.1.1.2.3*, jobo.2.2.1.1.3*, jobo.2.2.1.2.1.1, jobo.2.2.1.2.1.2, jobo.2.2.1.2.1.3*, jobo.2.2.1.2.2.1, jobo.2.2.1.2.2.2, jobo.2.2.1.2.2.3*, jobo.2.2.1.2.3*, jobo.2.2.1.3*, jobo.2.2.2.1.1.1, jobo.2.2.2.1.1.2, jobo.2.2.2.1.1.3*, jobo.2.2.2.1.2.1, jobo.2.2.2.1.2.2, jobo.2.2.2.1.2.3*, jobo.2.2.2.1.3*, jobo.2.2.2.2.1.1, jobo.2.2.2.2.1.2, jobo.2.2.2.2.1.3*, jobo.2.2.2.2.2.1, jobo.2.2.2.2.2.2, jobo.2.2.2.2.2.3*, jobo.2.2.2.2.3*, jobo.2.2.2.3*, jobo.2.2.3*, jobo.2.3*, jobo.3.1.1.1.1.1, jobo.3.1.1.1.1.2, jobo.3.1.1.1.1.3*, jobo.3.1.1.1.2.1, jobo.3.1.1.1.2.2, jobo.3.1.1.1.2.3*, jobo.3.1.1.1.3*, jobo.3.1.1.2.1.1, jobo.3.1.1.2.1.2, jobo.3.1.1.2.1.3*, jobo.3.1.1.2.2.1, jobo.3.1.1.2.2.2, jobo.3.1.1.2.2.3*, jobo.3.1.1.2.3*, jobo.3.1.1.3*, jobo.3.1.2.1.1.1, jobo.3.1.2.1.1.2, jobo.3.1.2.1.1.3*, jobo.3.1.2.1.2.1, jobo.3.1.2.1.2.2, jobo.3.1.2.1.2.3*, jobo.3.1.2.1.3*, jobo.3.1.2.2.1.1, jobo.3.1.2.2.1.2, jobo.3.1.2.2.1.3*, jobo.3.1.2.2.2.1, jobo.3.1.2.2.2.2, jobo.3.1.2.2.2.3*, jobo.3.1.2.2.3*, jobo.3.1.2.3*, jobo.3.1.3*, jobo.3.2.1.1.1.1, jobo.3.2.1.1.1.2, jobo.3.2.1.1.1.3*, jobo.3.2.1.1.2.1, jobo.3.2.1.1.2.2, jobo.3.2.1.1.2.3*, jobo.3.2.1.1.3*, jobo.3.2.1.2.1.1, jobo.3.2.1.2.1.2, jobo.3.2.1.2.1.3*, jobo.3.2.1.2.2.1, jobo.3.2.1.2.2.2, jobo.3.2.1.2.2.3*, jobo.3.2.1.2.3*, jobo.3.2.1.3*, jobo.3.2.2.1.1.1, jobo.3.2.2.1.1.2, jobo.3.2.2.1.1.3*, jobo.3.2.2.1.2.1, jobo.3.2.2.1.2.2, jobo.3.2.2.1.2.3*, jobo.3.2.2.1.3*, jobo.3.2.2.2.1.1, jobo.3.2.2.2.1.2, jobo.3.2.2.2.1.3*, jobo.3.2.2.2.2.1, jobo.3.2.2.2.2.2, jobo.3.2.2.2.2.3*, jobo.3.2.2.2.3*, jobo.3.2.2.3*, jobo.3.2.3*, jobo.3.3*, jobo.4* Anyone knows how this can be simplified and controlled by a variable int depth=123; for example? Thanks
This option avoids recursion, and simply counts as you would when deciding the next element in the sequence: private static class LevelGenerator implements Iterator<String> { private int[] current; // min,min,min => min,min,min+1 => ... max,max,max private int min, max; // at each position in current[] array private String next; // to be returned when next() is called public LevelGenerator(int levels, int min, int max) { this.current = new int[levels]; for (int i=0; i<levels; i++) this.current[i] = min; this.next = output(); this.min = min; this.max = max; } /** * Int array to string */ private String output() { StringBuilder sb = new StringBuilder(); for (int i : current) sb.append("." + i); return sb.toString(); } /** * Updates current and next * counts as a human would: increments the last index that is not yet `max`, * and then places all elements after it to `min` */ private String step() { for (int i=current.length-1; i>=0; i--) { if (current[i] < max) { current[i] ++; for (int j=i+1; j<current.length; j++) { current[j] = min; } return output(); // next step is ready } } return null; // no next step } #Override public String next() { if (next == null) throw new IllegalStateException("iteration is finished"); String output = next; next = step(); return output; } #Override public boolean hasNext() { return next != null; } } public static void main(String ... args) { LevelGenerator l = new LevelGenerator(3, 1, 4); while (l.hasNext()) { System.out.println("job" + l.next()); } } The output for this example would be: job.1.1.1 job.1.1.2 job.1.1.3 job.1.1.4 job.1.2.1 job.1.2.2 job.1.2.3 job.1.2.4 job.1.3.1 job.1.3.2 job.1.3.3 job.1.3.4 job.1.4.1 job.1.4.2 job.1.4.3 job.1.4.4 job.2.1.1 ... job.4.4.4
You can use Recursion (see wiki https://en.wikipedia.org/wiki/Recursion_(computer_science)) for example (draft, not checking) #Test public void buildTaskList1() { String jobName ="job"; int depth=5; int max=3; List<String> tasks = new ArrayList<>(); for (long i = 1; i <= max; i++) { buildTaskListRecursion(max, depth, tasks, jobName + "."+i); } tasks.add(jobName+"."+(max+1)+"*"); } public void buildTaskListRecursion(int max,int depth, List<String> tasks, String jobName){ String last=""; for (long j = 1; j <= max; j++) { if (j==max){ last="*"; tasks.add(jobName+"."+j+last); }else { depth--; if(depth > 0) { buildTaskListRecursion(max, depth, tasks, jobName+"."+j); } else { tasks.add(jobName+"."+j); } } } }
Yes 1. Support indexes Create a stack of indexes of the size of depth. 2. Handle the levels properly You need a currentDepth index to know where you were. This is 0 at first. Whenever an item is increased, push a new item to the stack with 0 as index. Whenever an item is going beyond max, pop it from the stack and increment the previous element. When the first element is popped, you completed all the work 3. You will need to logically know where you were. Alternatively you could generate code But that's much more complicated. EDIT In agreement with Bdzzaid's legitimate request, I will briefly talk about the Composite Design Pattern. First, let's see a diagram from the page he shared with us: Source: https://dzone.com/articles/composite-design-pattern-in-java-1 That's a good read I can wholeheartedly recommend to future readers. The idea is that we use the composition of very similar components in a tree-like manner. The pattern is applied on a stack in our case, which can be thought about as a tree having a single branch in all cases. The reason this is beneficial to think about in this way is that we might want to add support for multiple loops, maybe even in an assymmetryc manner at some point. Now, the components are the levels/indexes in our case and they, together form a composition of the stack (or, in more general terms, the tree). This pattern can be reused in many different situations, so it is advisable to get familiar with it if you not already have.
String index out of range in Java
I am aware there are multiple threads like my assignment below, but I just can't figure it out. I can't exactly figure out the mistake. Help would be appreciated. I am trying to do this program: Everything works fine unless I input the same chains or similar (for example ACTG and ACTG or ACTG and ACTGCCCC), when it tells me string index out of range This is that part of my code: int tries=0; int pos=-1; int k; for (int i=0; i<longDNA.length(); i++) { tries=0; k=i; for (int j=0; j<shortDNA.length(); j++) { char s=shortDNA.charAt(j); char l=longDNA.charAt(k); if (canConnect(s,l)) { tries+=1; k+=1; } } if (tries==shortDNA.length()-1) { pos=i-1; break; } }
Let's call the two DNA strings longer and shorter. In order for shorter to attach somewhere on longer, a sequence of bases complementary to shorter must be found somewhere in longer, e.g. if there is ACGT in shorter, then you need to find TGCA somewhere in longer. So, if you take shorter and flip all of its bases to their complements: char[] cs = shorter.toCharArray(); for (int i = 0; i < cs.length; ++i) { // getComplement changes A->T, C->G, G->C, T->A, // and throws an exception in all other cases cs[i] = getComplement(cs[i]); } String shorterComplement = new String(cs); For the examples given in your question, the complement of TTGCC is AACGG, and the complement of TGC is ACG. Then all you have to do is to find shorterComplement within longer. You can do this trivially using indexOf: return longer.indexOf(shorterComplement); Of course, if the point of the exercise is to learn how to do string matching, you can look at well-known algorithms for doing the equivalent of indexOf. For instance, Wikipedia has a category for String matching algorithms.
I tried to replicate your full code as fast as I could, I'm not sure if I fixed the problem but you don't get any errors. Please try it and see if it works. I hope you get this in time and good luck! import java.util.Arrays; public class DNA { public static void main(String[] args) { System.out.println(findFirstMatchingPosition("ACTG", "ACTG")); } public static int findFirstMatchingPosition(String shortDNA, String longDNA) { int positionInLong = 0; int positionInShort; while (positionInLong < longDNA.length()) { positionInShort = 0; while(positionInShort < shortDNA.length()) { String s = shortDNA.substring(positionInShort, positionInShort + 1); if(positionInShort + positionInLong + 1 > longDNA.length()) { break; } String l = longDNA.substring(positionInShort + positionInLong, positionInShort + positionInLong + 1); if(canConnect(s, l)) { positionInShort++; if(positionInShort == shortDNA.length()) { return positionInLong; } } else { break; } } positionInLong++; if(positionInLong == longDNA.length()) { return -1; } } return -1; } private static String[] connections = { "AT", "TA", "GC", "CG" }; private static boolean canConnect(String s, String l) { if(Arrays.asList(connections).contains((s+l).toUpperCase())) { return true; } else { return false; } } }
I finally changed something with the k as Faraz had mentioned above to make sure the charAt does not get used when k overrides the length of the string and the program worked marvelously! The code was changed to the following: int tries=0; int pos=-1; int k; for (int i=0; i<longDNA.length(); i++) { tries=0; k=i; for (int j=0; j<shortDNA.length(); j++) { if (k<longDNA.length()) { char s=shortDNA.charAt(j); char l=longDNA.charAt(k); if ((s=='A' && l=='T') || (s=='T' && l=='A') || (s=='G' && l=='C') || (s=='C' && l=='G')) { tries+=1; k+=1; } } } if (tries==shortDNA.length()) { pos=i; break; } } I am not sure how aesthetically pleasing or correct this excerpt is but - it completely solved my problem, and just 2 minutes before the deadline! :) A huge thanks to all of you for spending some time to help me!!
Where can I use threads to improve these methods?
Okay so for my project in my CSC330 class I am supposed to use threads to quickly find the answer to queries in a massive data set. Each item in the array is a user and the string is a collection of sites they visited on a website identified by number. Example (the array is String users[]) users[1] = "1 4 5 7" users[2] = "1 2 7 17 10" users[3] = "6" The queries are: are there more than ___ users who looked at X What percent of users looked at X Are there more users who looked at X than Y How many users viewed X ____ number of times What percent of users looked at X more than Y there are about a million users in this array and we had to solve the following queries without threads on a smaller scale version of the data for testing. All of mine work. Now I need to switch to the massive text file and I need to use threads to increase the speed. I'm wondering where it would be beneficial and how I could implement these threads. I will supply my code for solving each query. I'm thinking that I could use multiple threads to go through parts of the array at the same time but I'm not sure how to execute this. public boolean query1(String num, String pageName){ if(num == null){ return false; } else { int userCount = 0; int pageNum = convert(pageName); System.out.println(pageNum); String pageNumString = Integer.toString(pageNum); System.out.println(pageNumString); for(int i = 0; i < users.length; i++ ) { for(String entry : users[i].split(" ")) { if(entry.equals(pageNumString)) { userCount++; break; } } } if(userCount > Integer.parseInt(num)){ return false; } else{ return true; } } } public float query2(String pageName){ int userCount = 0; int pageNum = convert(pageName); String pageNumString = Integer.toString(pageNum); for(int i = 0; i < users.length; i++ ) { for(String entry : users[i].split(" ")) { if(entry.equals(pageNumString)) { userCount++; break; } } } float percentage = (userCount*100.0f)/users.length; return percentage; } public boolean query3(String pageName, String pageName2){ int userCount1 = 0; int userCount2 = 0; String pageNumString = Integer.toString(convert(pageName)); String pageNumString2 = Integer.toString(convert(pageName2)); for(int i = 0; i < users.length; i++ ) { for(String entry : users[i].split(" ")) { if(entry.equals(pageNumString)) { userCount1++; break; } } for(String entry : users[i].split(" ")) { if(entry.equals(pageNumString2)) { userCount2++; break; } } } return userCount1 > userCount2; } public int query4(String pageName, int numTimes){ int userCount = 0; String pageNumString = Integer.toString(convert(pageName)); for(int i = 0; i < users.length; i++ )//runs through each user { int pageCount = 0; for(String entry : users[i].split(" "))// runs through each user's pages { if(entry.equals(pageNumString)) { pageCount++; // each time page is found page count increments 1 } } // once done running through user's pages if(pageCount == numTimes){ // check if the number of pages is equal to the number given userCount++; // if so increment userCount } } return userCount; } public float query5(String pageName, String pageName2){ int viewedMore = 0; int userCount1 = 0; int userCount2 = 0; String pageNumString = Integer.toString(convert(pageName)); String pageNumString2 = Integer.toString(convert(pageName2)); for(int i = 0; i < users.length; i++ ) { for(String entry : users[i].split(" ")){ userCount1 = 0; userCount2 = 0; if(entry.equals(pageNumString)) { userCount1++; break; } } for(String entry : users[i].split(" ")) { if(entry.equals(pageNumString2)) { userCount2++; break; } } if(userCount1 > userCount2){ viewedMore++; } } return viewedMore*100.0f/users.length; }
At the very least, in query3 and query5 you can spawn off threads for each of the two inner for-loops; there's no reason they must be run sequentially. And for any of the query functions, you can certainly split the array into sections. Since your data is growing large, that approach will most likely be faster than iterating over the data with the main thread. I would suggest providing the threads contiguous segments (e.g. index 0 to N-1; N to N+N-1 etc). This previous StackOverflow answer provides good reasoning why such an approach is most efficient. Once you get something working, you can play around with the number of threads to optimize. edit to address your comment below One approach would be to implement the strategy pattern, such that each of your Query are interchangeable across a client, where an executeQuery() call is the interface method. Think of having a client's call look something like interface Query { boolean executeQuery(); } // client code... Client client = new Client(...); client.setQuery(new Query3(String num, String pageNum)); client.query(); // calls query.executeQuery(); Within the concrete Query classes, you can define individual behaviors of what the threads would do. This is a rough example: public Query3 implements Query { Query3(String pageNum`, String pageNum2) { this.pageNum1=pageNum1; this.pageNum2=pageNum2; } boolean executeQuery() { for(int i = 0; i < users.length; i++ ) { SearchThread first = new SearchThread(pageNum1); SearchThread second = new SearchThread(pageNum2); first.run(); second.run(); } first.join(); second.join(); return first.userCount > second.userCount; } SearchThread extends Thread { String pageNumString; int userCount; SearchThread(String pageNumString) { this.pageNumString=pageNumString; } public void run() { // do your search over this segment of the array, adding up userCounts } Here is another StackOverflow question that describes how to run multiple threads over a single array, with some boilerplate code to use.
I have to return a value from a function that is called multiple times and I am unable to do that
I am stuck. The following function is supposed to return currVm, an integer. But if I make a return I will break the loop and next time when this function is called,the same process will begin again. What shall I do, so that I continue from where I left off ? I tried making static variables but I that didn't help me. #Override public int getNextAvailableVm() { Set<String> dataCenters = confMap.keySet(); for (String dataCenter : dataCenters) { LinkedList<DepConfAttr> list = confMap.get(dataCenter); Collections.sort(list, new MemoryComparator()); int size = list.size() - 1; int count = 0; while(size >= 0) { DepConfAttr dca = (DepConfAttr)list.get(count); int currVm = dca.getVmCount(); int c = 0; while(c <= currVm) { allocatedVm(currVm); c++; return currVm; } count++; size--; } } return 0; } The for-each loop assigns a new data center that acts as a key for the confMap.The list that I get as a value, is sorted.Then a loop is run till it escapes its size.Inside this while loop, another while loop is run from where a function named allocatedVm of the inherited class is called. A parameter named currVm is passed to it. This is the variable that I need to return. What shall I do to return this variable ? I have to start from I left off. I mean the next call should appear to be the next step, whatever it was, while executing the loop.
Add List<Integer> object to your class, and change your method as follows: private Iterator<Integer> availableVms = null; #Override public int getNextAvailableVm() { if (availableVms != null) { if (availableVms.hasNext()) { return availableVms.next(); } return 0; } List<Integer> tmp = new ArrayList<Integer>(); Set<String> dataCenters = confMap.keySet(); for (String dataCenter : dataCenters) { LinkedList<DepConfAttr> list = confMap.get(dataCenter); Collections.sort(list, new MemoryComparator()); int size = list.size() - 1; int count = 0; while(size >= 0) { DepConfAttr dca = (DepConfAttr)list.get(count); int currVm = dca.getVmCount(); int c = 0; while(c <= currVm) { allocatedVm(currVm); c++; tmp.add(currVm); } count++; size--; } } availableVms = tmp.iterator(); return availableVms.hasNext() ? availableVms.next() : 0; } The idea is to pre-generate the entire list, and store its iterator for future use. Before entering the method you check if the availableVms iterator has been prepared. If it has been prepared, grab the next item off of it if it's available; otherwise, return zero. If the list has not been prepared yet, run your algorithm, and add the results to a temporary list tmp. Once the list is ready, grab its iterator, and use it for subsequent invocations.
Why is this array giving a null pointer exception?
I'm trying to implement a dictionary with a hash table (not using Java's provided hash table classes, but rather made from scratch). Below is the find() method from my Dictionary class, used to detect whether or not a key is in the table when inserting/removing. If the key is already in the table, it returns a score associated with the key (elements in the table are inserted as pairs of key/score into LinkedLists in each table position). If not, it returns -1. I am running a supplied test program to determine if my Dictionary class works, but I am encountering a NullPointerException when reaching a certain point. Included below is the particular test. Why would this exception be coming up? (I can provide more code if needed!) Find: public int find(String config) { for (int i = 0; i < dictSize; i++) { if (dict[i] != null) { LinkedList<DictEntry> current = dict[i]; String currentConfig = current.peek().getConfig(); //Dictionary.java:66 if (currentConfig.equals(config)) { int currentScore = current.peek().getScore(); return currentScore; } } } return -1; } Insert: public int insert(DictEntry pair) throws DictionaryException { String entryConfig = pair.getConfig(); int found = find(entryConfig); //Dictionary.java:27 if (found != -1) { throw new DictionaryException("Pair already in dictionary."); } int entryPosition = hash(entryConfig); if (dict[entryPosition] == null) { //Dictionary.java:35 LinkedList<DictEntry> list = new LinkedList<DictEntry>(); dict[entryPosition] = list; list.add(pair); return 0; } else { LinkedList<DictEntry> list = dict[entryPosition]; list.addLast(pair); return 1; } } The test: // Test 7: insert 10000 different values into the Dictionary // NOTE: Dictionary is of size 9901 try { for (int i = 0; i < 10000; ++i) { s = (new Integer(i)).toString(); for (int j = 0; j < 5; ++j) s += s; collisions += dict.insert(new DictEntry(s,i)); //TestDict.java:69 } System.out.println(" Test 7 succeeded"); } catch (DictionaryException e) { System.out.println("***Test 7 failed"); } Exception stack trace: Exception in thread "main" java.lang.NullPointerException at Dictionary.find(Dictionary.java:66) at Dictionary.insert(Dictionary.java:27) at TestDict.main(TestDict.java:69)
peek() returns null that's why. You can have a nullity check prior to getConfig() call.