I made a method which finds a value in my ArrayList. I also copied this method so I could use it for my array but certain things such as the get and size don't work. I'm unsure how I'm supposed to restructure it.
public Product findProduct(String givenProduct) throws IllegalProductCodeException {
IllegalProductCodeException notFoundMessage
= new IllegalProductCodeException("Product was not found");
int size = rangeOfProducts.length;
int i = 0;
boolean productFound = false;
while (!productFound && i < size) { //While book hasn't been found and i is less than the size of the array
productFound = rangeOfProducts.get(i).getProductCode().equals(givenProduct);
//Checks whether the given value in the array's reference is equal to the given reference entered
i++; //if not then add 1
}
if (productFound) {
return rangeOfProducts.get(i - 1);
} else {
throw notFoundMessage;
}
}
The array alternative to .get(i) will be [i] and the alternative to .size() will be .length.
for (Product product : products) {
if (product.getProductCode().equals(givenProduct)) {
return product;
}
}
throw new IllegalProductCodeException("Product was not found");
Edit: Java 5's enhanced for loop is equivalent to
for (Iterator<Product> iter=products.iterator(); iter.hasNext(); ) {
Product product = iter.next();
Related
i have sorted an array with double value
Arrays.sort(banding);
then i want to setText with the highest value that have specific String value "CUKUP". If it's not "CUKUP" than it's must be "LEBIH" and i don't want any "LEBIH" String value as an output
if (banding[6].getKetTotal().equals("CUKUP")) {
untungtertinggi.setText(Double.toString(banding[6].harga));
} else if (banding[6].getKetTotal().equals("LEBIH")) {
if (banding[5].getKetTotal().equals("CUKUP")) {
untungtertinggi.setText(Double.toString(banding[5].harga));
}
}else if (banding[5].getKetTotal().equals("LEBIH")) {
if (banding[4].getKetTotal().equals("CUKUP")) {
untungtertinggi.setText(Double.toString(banding[4].harga));
}
}else if (banding[4].getKetTotal().equals("LEBIH")) {
if (banding[3].getKetTotal().equals("CUKUP")) {
untungtertinggi.setText(Double.toString(banding[3].harga));
}
}else if (banding[3].getKetTotal().equals("LEBIH")) {
if (banding[2].getKetTotal().equals("CUKUP")) {
untungtertinggi.setText(Double.toString(banding[2].harga));
}
}else if (banding[2].getKetTotal().equals("LEBIH")) {
if (banding[1].getKetTotal().equals("CUKUP")) {
untungtertinggi.setText(Double.toString(banding[1].harga));
}
}else if (banding[1].getKetTotal().equals("LEBIH")) {
if (banding[0].getKetTotal().equals("CUKUP")) {
untungtertinggi.setText(Double.toString(banding[0].harga));
}
}
this coding is still wrong because when all arrays have String value "CUKUP" it doesn't put the highest double value as an output
It is not clear what is supposed to be output if the checks fail, so I'm guessing 0.0, but it could be adjusted.
The approach, if I followed the OP's logic, can be condensed to a loop, reducing the amount of checking. The specific object type of the array banding was not specified, so I haphazardly used Banding as the object type -- that is probably not exactly correct.
NOTE: the assumption is that the array is properly sorted.
Arrays.sort(banding);
setText(banding);
void setText(Banding[] banding) {
final int loc = banding.length - 1;
// if the highest is what we want, set and return
if (banding[loc].getKekTotal().equals("CUKUP")) {
untungtertinggi.setText(Double.toString(banding[loc].harga));
return;
}
// we run until one before the start of the array, as we check for the
// previous value; if we meet the criteria of [i] being LEBIH, and [i - 1]
// being CUKUP, then we set the value and return
for (int i = loc; i > 0; --i) {
if (banding[i].getKekTotal().equals("LEBIH") &&
banding[i - 1].getKetTotal().equals("CUKUP")) {
untungtertinggi.setText(Double.toString(banding[i - 1].harga));
return;
}
}
// no specific value found
untuntertinggi.setText(Double.toString(0.0));
}
This question already has answers here:
Why am I not getting a java.util.ConcurrentModificationException in this example?
(10 answers)
Closed 4 years ago.
If we write like this, there is a concurrent modification exception :
public static void main(String... args) {
List<String> listOfBooks = new ArrayList<>();
listOfBooks.add("Programming Pearls");
listOfBooks.add("Clean Code");
listOfBooks.add("Effective Java");
listOfBooks.add("Code Complete");
System.err.println("Before deleting : " + listOfBooks);
for (String book : listOfBooks) {
if (book.contains("Code")) {
listOfBooks.remove(book);
}
}
System.err.println("After deleting : " + listOfBooks);
}
On the other hand, if we write like this, there is NO concurrent modification exception !
Notice that code is exact the same, except the strings for compare, in first example it is a Code, and in second it is a Java
public static void main(String... args) {
List<String> listOfBooks = new ArrayList<>();
listOfBooks.add("Programming Pearls");
listOfBooks.add("Clean Code");
listOfBooks.add("Effective Java");
listOfBooks.add("Code Complete");
System.err.println("Before deleting : " + listOfBooks);
for (String book : listOfBooks) {
if (book.contains("Java")) {
listOfBooks.remove(book);
}
}
System.err.println("After deleting : " + listOfBooks);
}
I'm using Netbeans 8.2, Windows 7 32bit, with JDK 1.8.0_131
What's wrong ?
List.remove() will not throw ConcurrentModificationException when it removes the second last element from the list.
Quoting from this Java Bug (JDK-4902078) .
When the Collections Framework was added to the platform it was deemed too expensive to check for comodification once rather than twice per iteration; the check was made on Iterator.next rather than Iterator.hasNext. Expert reviewers thought this was sufficient. They were unaware that it fails to detect one important case: if an element is removed from the list immediately prior to the final call to hasNext in an iteration, the call returns false and the iteration terminates, silently ignoring the last element on the list.
You can also check this answer :-
https://stackoverflow.com/a/8189786/1992276
There are two ways used to iterate over an collection: enumeration and iterator.
First one allows for the collection to be modified during iteration (fail slow), second does not (fail fast). In a for-each loop you are using an iterator, so any modification to the collection, during it's iteration would cause an exception.
You have 3 choices, to solve this problem:
Use an iterator instead:
Iterator<String> bookIt = listOfBooks.iterator();
while(bookIt.hasNext()){
String book = bookIt.next();
if (book.contains("Java")) {
bookIt.remove();
}
}
Create a new list with only acceptable elements (filter out the unwanted):
List<String> booksWithNoCode = listOfBooks.stream()
.filter(book-> !book.contains("Code"))
.collect(toList())
Use Collection.removeIf(), you will remove all elements from the list, that are matching given criteria.
listOfBooks.removeIf(book-> book.contains("Code"))
You can find more information in this post and here.
You can't modify the listOfBooks while you are iterating though it with the for each loop.
edit:
for (String book : listOfBooks) {
if (book.contains("Code")) {
listOfBooks.remove(book);
}
}
Is the same as:
for (Iterator<String> i = listOfBooks.iterator(); i.hasNext();) {
String book = i.next();
if (book.contains("Code")) {
listOfBooks.remove(book);
}
}
http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/tip/src/share/classes/java/util/ArrayList.java
The key in the arraylist code is:
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
/*
* Private remove method that skips bounds checking and does not
* return the value removed.
*/
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
}
and the iterator code:
public boolean hasNext() {
return cursor != size;
}
#SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
The cursor always points to the next element so when you get the "Effective Java" i = 2 but cursor is 3.
When you call the remove the cursor is at 3 and the size is 4.
The size is then decremented by the remove and now cursor == size and the next hasNext() returns false ending the loop.
I'm having trouble writing a for-each loop that searches the arraylist and returns the county's name within the continent that has the highest gdp. Here's my code for it right now. (ElementsList is the original ArrayList)
public Country highestGdp(String continent) {
boolean flag;
for (Country cont : ElementsList) {
if (cont.getContinent().equals(continent)) {
ArrayList<Country> TMP1 = new ArrayList<Country>();
TMP1.add(cont);
for (Country gdp : TMP1) {
double max = 0;
if (max < gdp.getGDP()) {
max = gdp.getGDP();
}
if (gdp.getGDP() == max) {
ArrayList<Country> TMP2 = new ArrayList<Country>();
TMP2.add(gdp);
}
return gdp;
}
}
}
return null;
}
Each time you find a country in the right continent, you can check to see if it is greater than the max so far. Don't need to loop through all of them each time.
public Country highestGdp(String continent) {
boolean flag;
Country maxCountry = null;
for (Country cont : ElementsList) {
if (cont.getContinent().equals(continent)) {
if (maxCountry == null) maxCountry = cont;
if (maxCountry.getGDP() < gdp.getGDP()) {
maxCountry = cont;
}
}
}
return maxCountry;
}
Sorry for saying it but Your code is a little messy ;)
To shortly solve Your problem, try to move max declaration before the loop like this:
[...]
double max = 0;
for(Country gdp : TMP1){
[...]
We can see that TMP2 is completely useless, remove it:
// ArrayList<Country> TMP2 = new ArrayList<Country>();
// TMP2.add(gdp);
You create TMP1 list always with only 1 element and then iterate over it. This is also useless, You can do the code directly on the element You are adding to the list.
First iteration over ElementList is a list of Country elements, but the element You iterate is called cont (=continent) which is a Continent and not the Country. Is it intended to use Country class to cover both: Countries and Continents? Do You plan to have a tree structure like "Continents contains many Countries"?
Final code to solve problem from Your original question should be like this:
public Country highestGdp(String continent){
Country countryWithMaxGdp = null;
for(Country cont: ElementsList ){
if(cont.getContinent().equals(continent)){
if(countryWithMaxGdp == null || countryWithMaxGdp.getGDP() < cont.getGDP()){
countryWithMaxGdp = cont;
}
}
}
return countryWithMaxGdp;
}
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.
I have two arraylist name preBusinessList, businessList. In business List I have data from server, and in preBusinessList is the local one. In lists I have id, count value Betterly demonstrate as below
Now I wanted to make a newBusinessList like this
How can I do it in java, please help me to solve this
Then I would use a map to do the merge using id as the key and convert it back to your list of (id,value) pairs
You can use:
Collections.sort(new ArrayList<...>(preBusinessList).addAll(businessList), comparator)
Where comparator is a class that implements Comparator interface (will be responsible for sorting as you wish)
assumming i understood your problem correctly (big if...):
also, i assume each element in the lists is a Pair - as it looks from your data (just a dumb wrapper class that holds 2 integers). if its some other class you'll need to adjust this code.
private Map<Integer,Integer> finalValues = new HashMap<Integer,Integer>();
for (Pair<Integer,Integer> entry : preBusinessList) {
finalValues.put(entry.getFirst(), entry.getSecond());
}
//2nd list overwrites values from 1st (anything not overwritten remains)
for (Pair<Integer,Integer> entry : businessList) {
finalValues.put(entry.getFirst(), entry.getSecond());
}
ArrayList<Pair<Integer,Integer>> finalList = new ArrayList<>();
for (Map.Entry<Integer,Integer> entry : finalValues) {
finalList.add(new Pair(entry.getKey(), entry.getValue());
}
//and now sort the list
Collections.sort(finalList, new Comparator<Pair<Integer,Integer>> {
int compare(Pair<Integer,Integer> a, Pair<Integer,Integer>b) {
return a.getFirst.compareTo(b.getFirst()); //compare by 1st number in pair only
}
});
Assuming something like:
public class Info {
public int id;
public int info;
}
You could merge them on the basis of wanting the keep the one with higher info field as follows:
// Assumes:
// - that the ArrayLists are sorted to have id in order going up
// - no repeated ids in a or in b (but same id can be in both a and b)
ArrayList<Info> merge(ArrayList<Info> a, ArrayList<Info> b) {
int aLength = a.size();
int bLength = b.size();
int ai = 0;
int bi = 0;
ArrayList<Info> result = new ArrayList<Info>();
while ((ai < aLength) && (bi < bLength))
Info aInfo = a.get(ai);
Info bInfo = b.get(bi);
if (aInfo.id == bInfo.id) {
if (aInfo.info >= bInfo.info) result.add(aInfo);
else result.add(bInfo);
ai++;
bi++;
}
else if (aInfo.id < bInfo.id) {
result.add(aInfo);
ai++;
}
else {
result.add(bInfo);
bi++;
}
}
// Add the remaining terms - only one of the loops will actually do anything
for (; ai<aiLength; ai++) {
result.add(a.get(ai));
}
for (; bi<biLength; bi++) {
result.add(b.get(bi));
}
}
Pseudocode :
Iterate over preBusinessList.
Fetch key and see if this key(1,2,3,4,5,6) exists in businesslist
If yes conitnue
Else If no, then add it to businesslist
for(Map.Entry<Integer, Integer> keyValue : preBusinessList.entrySet()) {
if(!businesslist.containsKey(keyValue.getKey())) {
businesslist.put(keyValue.getKey(), keyValue.getValue());
}
}
Updated Answer as per new requirements
boolean ifExists = false;
for(PlaceItems itemPreBusinessList : preBusinessList) {
ifExists = false;
for(PlaceItems itemBusinessList : businessList) {
if(itemBusinessList.businessId == itemPreBusinessList.businessId) {
// Already exists
ifExists = true;
break;
}
}
if(!isExists) {
businessList.add(itemPreBusinessList);
}
}