This question already has answers here:
Fixed size queue which automatically dequeues old values upon new enqueues
(15 answers)
Closed 8 years ago.
I have an extra ordinary requirement of having a Java object array list (or list initialized as an ArrayList) which will be continuously updated and is supposed to hold only the latest 5 items with the objects to be sorted in a descending order of they were added.
How could this be accomplished? I need to come up with a solution within Java SE 7 preferably using no 3rd party library.
NOTE For those who mark this question as a duplicate, you do not seem to understand the requirement of using ArrayList for this case and that Queues and ArrayLists are different object types as well as Java and C# are different languages. Do you think Stackoverflow's internal search engine is not as good as you are in locating the duplicate questions?
When marking a question as "duplicate", make sure you link a true duplicate, please.
Not sure about the descending order, but this shows one way of fixing the size
class BoundedArrayList<E> extends ArrayList<E> {
private int fixedCapacity;
public BoundedArrayList(int fixedCapacity) {
super(fixedCapacity);
this.fixedCapacity = fixedCapacity;
}
#Override
public boolean add(E e) {
// is it about to cross limit ? removing it in advance
if(this.size() > fixedCapacity - 1) {
E element = this.remove(fixedCapacity - 1);
System.out.println("Removed due to overflow : " + element);
}
this.add(0, e);
return true;
}
public static void main(String[] args) {
BoundedArrayList<Integer> list = new BoundedArrayList<Integer>(5);
for(int i =0 ; i < 10; i++) {
list.add(i);
System.out.println(list);
}
}
}
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
Some background: I am new to Java and am taking a basic java class. I am currently on the final project for the class and completed everything except for this last bit of code. For some reason, I am having the toughest time deleting an element from an array list. Here is the code I am working on:
public static void delete(String bookID) {
for (book eachElement : catalog) {
if (eachElement.getBookID().equals(bookID)) {
catalog.remove(eachElement);
return;
}
}
}
code executes, no run time errors but it won't delete anything.
also, I know everything works prior to the remove statement because I have another method that computes calculations using the same exact for and if statement with a select bookID string.
You should not and cannot remove an Element from a Collection while being in a forEach loop.
Please read the Documentation for ArrayList in Java.
https://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html
There you actually can see, that ArrayList.remove(Object o), removes o if it is in the list, so your method is not needed.
So the answer is, find the book Object with your ID and then remove it. Or better use a Map to store your data.
In your case it would be
Book b = null;
for(Book book : books) {
if(book.getBookId().equals(bookId)) {
b = book.getBookId();
break;
}
}
books.remove(b);
Or if you are into Java8 which you really should be :D
books.stream().filter(b -> b.getBookId().equals(bookId)).getFirst().ifPresent(books::remove);
You need to use iterator, otherwise you will get java.util.ConcurrentModificationException
public static void delete(String bookID) {
for (Iterator<Book> it = catalog.listIterator(); it.hasNext(); ) {
Book book = it.next();
if (book.getBookID().equalsIgnoreCase(bookID)) {
it.remove(book);
return;
}
}
}
Note: equalsIgnoreCase is used to discard case differences.
java.util.ConcurrentModificationException is thrown, because you are doing 2 operations on the list: iteration and removal. So, actually, there is another approach - copy the list on each step of iteration.
public static void delete(String bookID) {
for (Book book : new ArrayList<>(catalog)) {
if (book.getBookID().equalsIgnoreCase(bookID)) {
catalog.remove(book);
return;
}
}
}
Note: Because of performance considerations (quadratic memory usage and linear removal on each step), I don't recommend the last approach. I give this example only to stress out the underlying reason why java.util.ConcurrentModificationException is thrown.
Removal of elements, while an iterator is being used, is undefined.The better approach would be to use removeIf.
catalog.removeIf(eachElement -> eachElement.getBookID().equals(bookId));
You need to use iterator in order to delete item while using loop .
also double check if the id exist (make some System.out.println("test") and check if it is entering the scope).
This question already has answers here:
What are the possible problems caused by adding elements to unsynchronized ArrayList's object by multiple threads simultaneously?
(4 answers)
Java MultiThreading behaviour explanation
(4 answers)
Why is arraylist's size not right when multiple threads add elements into it?
(5 answers)
Data race in Java ArrayList class
(3 answers)
Closed 4 years ago.
I've made the following code to run multiple thread through a non thread safe object (here an ArrayList) :
import java.time.LocalDateTime;
import java.util.List;
import java.util.ArrayList;
public class A implements Runnable {
String name;
static List<Integer> list = new ArrayList();
private static Object lock = new Object();
A(String name) {
this.name = name;
}
#Override
public void run() {
for(int i = 1; i <= 1000; i++) {
list.add(i);
}
System.out.println(list.size());
}
}
I was expecting this code just to produce wrong answers since ArrayList is not thread-safe. But instead I get this error :
Exception in thread "Thread-1" 1003
2401
2799
3799
java.lang.ArrayIndexOutOfBoundsException: 109
at java.util.ArrayList.add(Unknown Source)
at threads.A.run(A.java:16)5123
at java.lang.Thread.run(Unknown Source)
Exception in thread "Thread-5" java.lang.ArrayIndexOutOfBoundsException: 4164
at java.util.ArrayList.add(Unknown Source)
at threads.A.run(A.java:16)
at java.lang.Thread.run(Unknown Source)
6123
Can anyone explain to me what is leading to this specific error?
Well, you are using a non thread-safe collection in a multi threaded environment without any synchronization.
Let's examine the add method, where you get the exception:
/**
* Appends the specified element to the end of this list.
*
* #param e element to be appended to this list
* #return <tt>true</tt> (as specified by {#link Collection#add})
*/
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
When multiple threads call this method at the same time, it is quite possible that ensureCapacityInternal(size + 1) verifies there is enough space for 1 new element, but then multiple threads try to add an element at the same time, so elementData[size++] throws ArrayIndexOutOfBoundsException for some of them.
ArrayList is not a thread-safe class.
Underlying storage for elements is Object[] which is an array. Any array requires the allocation space in memory which is predefined in the compile time. However, when an ArrayList "wants" to add the new element (beyond the underlying array bound), several things have to be done (without your knowledge). Underlying array gets a new (increased) length. Every element of the old array is copied to the new array, and then the new element is added. So, you can expect the ArrayIndexOutOfBoundsException exception when an ArrayList is used in multi-thread environment.
You are adding elements too fast so ArrayList#add() -> grow() -> newCapacity() can't calculate the correct capacity to allocate the memory for all of the elements coming in.
private void add(E e, Object[] elementData, int s) {
if (s == elementData.length)
elementData = grow();
elementData[s] = e;
size = s + 1;
}
At some point of time, the condition s == elementData.length inside ArrayList#add says that there is a space for a new element A. Immediately after that other threads put their elements into the list. Now there is no space for A and elementData[s] = e; throws an exception.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
Java 8 provides a bunch of functional interfaces that we can implement using lambda expressions, which allows functions to be treated as
first-class citizen (passed as arguments, returned from a method, etc...).
Example:
Stream.of("Hello", "World").forEach(str->System.out.println(str));
Why functions considered as first-class citizens are so important? Any example to demonstrate this power?
The idea is to be able to pass behavior as a parameter. This is useful, for example, in implementing the Strategy pattern.
Streams API is a perfect example of how passing behavior as a parameter is useful:
people.stream()
.map(person::name)
.map(name->new GraveStone(name, Rock.GRANITE)
.collect(Collectors.toSet())
Also it allows programmers to think in terms of functional programming instead of object-oriented programming, which is convenient for a lot of tasks, but is quite a broad thing to cover in an answer.
I think the second part of the question has been addressed well. But I want to try to answer the first question.
By definition there is more that a first-class citizen function can do. A first-class citizen function can:
be named by variables
be passed as arguments
be returned as the result of another function
participate as a member data type in a data structure (e.g., an array or list)
These are the privileges of being "first-class."
It's a matter of expressiveness. You don't have to, but in many practical cases it will make your code more readable and concise. For instance, take your code:
public class Foo {
public static void main(String[] args) {
Stream.of("Hello", "World").forEach(str->System.out.println(str));
}
}
And compare it to the most concise Java 7 implementation I could come out with:
interface Procedure<T> {
void call(T arg);
}
class Util {
static <T> void forEach(Procedure<T> proc, T... elements) {
for (T el: elements) {
proc.call(el);
}
}
}
public class Foo {
static public void main(String[] args) {
Util.forEach(
new Procedure<String>() {
public void call(String str) { System.out.println(str); }
},
"Hello", "World"
);
}
}
The result is the same, the number of lines a bit less :) Also note that for supporting Procedure instances with different number of arguments, you would have needed an interface each or (more practical) passing all the arguments as a single Parameters object. A closures would have been made in a similar way, by adding some fields to the Procedure implementation. That's a lot of boilerplate.
In fact, things like first-class "functors" and (non-mutable) closures have been around for a long time using anonymous classes, but they required a significant implementation effort. Lambdas just make things easier to read and write (at least, in most cases).
Here's a short program the shows (arguably) the primary differentiating factor.
public static void main(String[] args) {
List<Integer> input = Arrays.asList(10, 12, 13, 15, 17, 19);
List<Integer> list = pickEvensViaLists(input);
for (int i = 0; i < 2; ++i)
System.out.println(list.get(i));
System.out.println("--------------------------------------------");
pickEvensViaStreams(input).limit(2).forEach((x) -> System.out.println(x));
}
private static List<Integer> pickEvensViaLists(List<Integer> input) {
List<Integer> list = new ArrayList<Integer>(input);
for (Iterator<Integer> iter = list.iterator(); iter.hasNext(); ) {
int curr = iter.next();
System.out.println("processing list element " + curr);
if (curr % 2 != 0)
iter.remove();
}
return list;
}
private static Stream<Integer> pickEvensViaStreams(List<Integer> input) {
Stream<Integer> inputStream = input.stream();
Stream<Integer> filtered = inputStream.filter((curr) -> {
System.out.println("processing stream element " + curr);
return curr % 2 == 0;
});
return filtered;
}
This program takes an input list and prints the first two even numbers from it. It does so twice: the first time using lists with hand-written loops, the second time using streams with lambda expressions.
There are some differences in terms of the amount of code one has to write in either approach but this is not (in my mind) the main point. The difference is in how things are evaluated:
In the list-based approach the code of pickEvensViaLists() iterates over the entire list. it will remove all odd values from the list and only then will return back to main(). The list that it returned to main() will therefore contain four values: 10, 12, 20, 30 and main() will print just the first two.
In the stream-based approach the code of pickEvensViaStreams() does not actually iterate over anything. It returns a stream who else can be computed off of the input stream but it did not yet compute any one of them. Only when main() starts iterating (via forEach()) will the elements of the returned stream be computed, one by one. As main() only cares about the first two elements only two elements of the returned stream are actually computed. In other words: with stream you get lazy evaluation: streams are iterated only much as needed.
To see that let's examine the output of this program:
--------------------------------------------
list-based filtering:
processing list element 10
processing list element 12
processing list element 13
processing list element 15
processing list element 17
processing list element 19
processing list element 20
processing list element 30
10
12
--------------------------------------------
stream-based filtering:
processing stream element 10
10
processing stream element 12
12
with lists the entire input was iterated over (hence the eight "processing list element" messages). With stream only two elements were actually extracted from the input resulting in only two "processing stream element" messages.
This question already has answers here:
Java Set gets full
(2 answers)
Closed 8 years ago.
I loop through a copy of a set of objects, but it still gives me an error starting at this method:
private static Set<Updated> updates = new HashSet<>();
public static Set<GameObject> getGameObjects() {
Set<GameObject> objs = new HashSet<>();
for (Updated up : new HashSet<Updated>(updates)) {
if (up instanceof GameObject)
objs.add((GameObject) up);
}
return objs;
}
(Where the for loop is).
This only happens when there are quite a few GameObjects, and never occurs when there's only a few (like 7). Thank you!
The problem is that somebody in another thread changes the updates set while it is being copied in new HashSet<Updated>(updates).
You cannot do this without synchronization. Or use ConcurrentHashMap instead of HashSet
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
I have a situation that I need to fill an object array.
This is my code:
final class ObjectClass
{
List<ObjectClass> array;
private int data;
ObjectClass(int data)
{
this.data = data;
}
public void fillArray() {
array = new LinkedList<>();
for(int i = 0;i < array.size();i++)
{
data++;
array.add(new ObjectClass(data));
}
}
}
And i am getting no result with this. What is wrong with that?
Is it valid to add like this: array.add(new ObjectClass(data)) ?
There is no point about results and logic in this situation. I just want to make the ObjectClass's array with different data values. I saw, someone used a reference variable and stored it in an array, but is it valid to make it without it by creating only object?
Add a print method:
public void display() {
for(ObjectClass e : array) {
System.out.println(e);
}
}
The reason why nothing is happening is here:
for(int i = 0;i < array.size();i++)
The line before, you just created the array so it's still empty - therefore, the body of the loop isn't executed at all.
Every time you call fillArray, you are destroying the data (however it made its way in there) in the array with this:
array = new LinkedList<>();
First, change your field to use eager initialization instead, so you're not overwriting your field on every method call.
List<ObjectClass> array = new LinkedList<>();
Now, for your method. You don't enter the loop since array is always empty. Depending on what you're trying to accomplish, you should pass the object through, or create a copy of it n times.
public void fillArray(int times) {
for(int i = 0;i < times; i++) {
data++;
array.add(new ObjectClass(data));
}
}
Lastly, observe that, if the loop did work, data and array.size() would be equivalent (so long as you didn't remove anything). I'd rethink the purpose/intent of that variable.
Declare the List<ObjectClass> array as static, it will do what you are trying to achieve by creating a Class variable not at Object Level
The problem is the array (which is not actually an array by the way - it's mis-named) initially has size 0, so the method does nothing.
You have forgotten to consider how many numbers you want to "fill" the data structure with.