i get ConcurrentModificationException when adding an item [duplicate] - java

This question already has answers here:
ConcurrentModificationException despite using synchronized
(3 answers)
Closed 8 years ago.
im trying to save the manager id of distinct managers from collabs to managersId but i get an exeption "ConcurrentModificationException"
public void fillTree() throws SystemException, PortalException {
TreeNode nodeParent;
TreeNode nodeFils;
Set<Long> managersId = new HashSet<Long>();
UserVO user = new UserVO();
collabs = CollabLocalServiceUtil.getCollabs(-1, -1);
Iterator<Long> iter = managersId.iterator();
long id;
for (int i = 0; i < collabs.size(); i++) {
id = collabs.get(i).getManagerId();
synchronized (managersId) {
managersId.add((Long) id);
System.out.println(id);
}
}
while (iter.hasNext()) {
id = iter.next();//throw exeption
user = getUserById(id);
nodeParent = new DefaultTreeNode(user.getFullName(), root);
for (int j = 0; j < collabs.size(); j++) {
if (collabs.get(j).getManagerId() == user.getUserId()) {
nodeFils = new DefaultTreeNode(getUserById(
collabs.get(j).getUserId()).getFullName(),
nodeParent);
}
}
}
}
im using liferay portal

Edit based on question update.
In this new code the issue is with your iterator. You initialized the iterator and then modified the collection and then trying to use the dirty iterator. That is the cause of concurrent modification exception.
So the fix for this issue is simple. Just move Iterator<Long> iter = managersId.iterator(); after for loop. Try
public void fillTree() throws SystemException, PortalException {
TreeNode nodeParent;
TreeNode nodeFils;
Set<Long> managersId = new HashSet<Long>();
UserVO user = new UserVO();
collabs = CollabLocalServiceUtil.getCollabs(-1, -1);
long id;
for (int i = 0; i < collabs.size(); i++) {
id = collabs.get(i).getManagerId();
synchronized (managersId) {
managersId.add((Long) id);
System.out.println(id);
}
}
Iterator<Long> iter = managersId.iterator(); // Getting the new iterator with latest value.
while (iter.hasNext()) {
id = iter.next();//Now this wont throw exeption
user = getUserById(id);
nodeParent = new DefaultTreeNode(user.getFullName(), root);
for (int j = 0; j < collabs.size(); j++) {
if (collabs.get(j).getManagerId() == user.getUserId()) {
nodeFils = new DefaultTreeNode(getUserById(
collabs.get(j).getUserId()).getFullName(),
nodeParent);
}
}
}
}
OLD ANSWER
Firstly from your logic I think you are trying to get unique manager id as list. In this case you could use a Set.
As for your current problem if its executing in a multi thread environment you could use synchronized block like
List<Long> managersId = new ArrayList<Long>();
collabs = CollabLocalServiceUtil.getCollabs(-1, -1);
long id;
for (int i = 0; i < collabs.size(); i++) {
id = collabs.get(i).getManagerId();
synchronized (managersId) {
if (!managersId.contains(id)) {
managersId.add((Long) id);
}
}
}
Or else you could use java.util.concurrent.CopyOnWriteArrayList for concurrent list operation.
List<Long> managersId = new CopyOnWriteArrayList<Long>();
Also as a third option you can make a normal list synchronized by collections class
Collections.synchronizedList(managersId);

Related

NPE occurs when add an object in Array of ArrayList

How do I resolve this problem...
I wanna add object OrgDO in allOrgListArr[idx].
ArrayList<OrgDO>[] allOrgListArr = new ArrayList[Integer.parseInt(maxLv)+1];
for(int i = 0; i < Integer.parseInt(maxLv)+1; i++) {
allOrgListArr[i] = new ArrayList<OrgDO>();
}
for(OrgDO org : allOrgList.getOrgListList()) {
allOrgListArr[org.getORG_LEVEL()].add(org); // --> this part throws a NullPointerException
}
You need to be a bit more defensive in your programming and check that the index exists in the array and if so you also need to check that you have an object at that index
for(OrgDO org : allOrgList.getOrgListList()) {
int level = org.getORG_LEVEL();
if (level >= allOrgListArr.length()) {
continue; //or other error handling
}
List<OrgDO> list = allOrgListArr[level];
if (list == null) {
list = new ArrayList<OrgDO>();
allOrgListArr[level] = list;
}
list.add(org);
}

Is there a way to dynamically create a counter if such "month" exists?

I would like to enquire or get some reference as to how can I dynamically create a counter for each month if the exists ? Currently, I am retrieving the dates from a CSV file and store it in an ArrayList, from there I am comparing the dates to check whether if such month exists. If the month exists then "counter++". Afterwards, store the counter in a hashmap. I understand my code currently is an inefficient way of coding. How could I make it better ?
CODE
public HashMap<String, Integer> getDataPoint() {
//My function code
HashMap<String, Integer> numberOfPost = new HashMap<String, Integer>();
int janCounter = 0;
int febCounter = 0;
int marCounter = 0;
int aprCounter = 0;
int mayCounter = 0;
int juneCounter = 0;
int julyCounter = 0;
int augCounter = 0;
int septCounter = 0;
int octCounter = 0;
int novCounter = 0;
int decCounter = 0;
String pattern = "MMM";
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
OpenCsvReader reader = new OpenCsvReader();
ArrayList <STPost> STArray = reader.loadST("file_path");
Iterator STitr = STArray.iterator();
while (STitr.hasNext()) {
STPost St = (STPost) STitr.next();
Date retrievedate = St.getTime();
String strDate = sdf.format(retrievedate);
if(strDate.equals("Jan")) {
janCounter++;
}
else if (strDate.equals("Feb")) {
febCounter++;
}
else if (strDate.equals("Mar")) {
marCounter++;
}
else if (strDate.equals("Apr")) {
aprCounter++;
}
else if (strDate.equals("May")) {
mayCounter++;
}
else if (strDate.equals("June")) {
juneCounter++;
}
else if (strDate.equals("July")) {
julyCounter++;
}
else if (strDate.equals("Aug")) {
augCounter++;
}
else if (strDate.equals("Sept")) {
septCounter++;
}
else if (strDate.equals("Oct")) {
octCounter++;
}
else if (strDate.equals("Nov")) {
novCounter++;
}
else if (strDate.equals("Dec")) {
decCounter++;
}
numberOfPost.put("January", janCounter);
numberOfPost.put("Feburary", febCounter);
numberOfPost.put("March", marCounter);
numberOfPost.put("April", aprCounter);
numberOfPost.put("May", mayCounter);
numberOfPost.put("June", juneCounter);
numberOfPost.put("July", julyCounter);
numberOfPost.put("August", augCounter);
numberOfPost.put("September", septCounter);
numberOfPost.put("October", octCounter);
numberOfPost.put("November", novCounter);
numberOfPost.put("December", decCounter);
}
return numberOfPost
}
You can create an array of months and check if value exists there using indexOf method.
String months = "JanFebMarAprMayJunJulAugSepOctNovDec";
Integer idx = months.indexOf(strDate);
Thereafter you can use SimpleDateFormat("MMMM") pattern to put and get it into your map.
if(idx > -1) {
String longDate = new SimpleDateFormat("MMMM").format(retrievedate);
Integer current = numberOfPost.get(longDate);
if (current == null) {
current = 1;
} else {
current += 1;
}
numberOfPost.put(longDate, current);
}
Thereafter, you can use map iterator to display content of map.
You already have a good start. Using a the hash map will make the code much tidier.
You can replace all those if statements and put statements with the code below:
if (!numberOfPosts.containsKey(strDate)) {
numberOfPosts.put(strDate, 0);
}
numberOfPosts.put(strDate, numberOfPosts.get(strDate) + 1);
The if statement will create a dictionary entry if there is not one with the key of strDate. The value of the entry is set to 0.
numberOfPosts.put(strDate, numberOfPosts.get(strDate) + 1)
The line above increments by 1 the dictionary entry with the key of strDate.

kafka.api.OffsetRequest - unable to retrieve results

Am working through the task of determining ConsumerLag and need to retrieve the current Producer Offset as follows:
PartitionOffsetRequestInfo partitionOffsetRequestInfo =
new PartitionOffsetRequestInfo(OffsetRequest.LatestTime(), 100);
List<TopicAndPartition> partitions = new ArrayList<>();
for(int i = 0; i < partitionMetadataList.size(); i++) {
TopicAndPartition topicAndPartition = new TopicAndPartition(topic, i);
partitions.add(topicAndPartition);
tuple2List.add(new Tuple2<>(topicAndPartition, partitionOffsetRequestInfo));
}
Tuple2<TopicAndPartition, PartitionOffsetRequestInfo>[] tuple2Array =
tuple2List.parallelStream().toArray(Tuple2[]::new);
WrappedArray<Tuple2<TopicAndPartition, PartitionOffsetRequestInfo>> wrappedArray =
Predef.wrapRefArray(tuple2Array);
scala.collection.immutable.Map<TopicAndPartition, PartitionOffsetRequestInfo> offsetRequestInfoMap =
(scala.collection.immutable.Map<TopicAndPartition, PartitionOffsetRequestInfo>)
scala.Predef$.MODULE$.Map().apply(wrappedArray);
OffsetRequest offsetRequest = new OffsetRequest(offsetRequestInfoMap, (short)0,
0, OffsetRequest.DefaultClientId(), Request.OrdinaryConsumerId());
Looking at the OffsetResponse am presented with an array of UnknownTopicOrPartitionException offsets. If I pass in (short)1 for the versionId (as I have for calls to OffsetFetchResponse) I get a NetworkReceive.readFromReadableChannel exception when I try to retrieve the results.
Questions:
a. Is there a better way to get current producer offset?
b. Why doesn't the OffsetRequest call work with VersionId = 1?
Edit:
Note that Im able to use this channel to retrieve ConsumerOffset so I know it works.
I can retrieve the values using the cmdline:
kafka-consumer-groups --bootstrap-server hostname:9092 --describe --new-consumer --group test_consumer
Edit:
Attempted to reuse sample scala (rewritten as Java) code:
KafkaConsumer<String, String> kafkaConsumer = getConsumer();
List<org.apache.kafka.common.TopicPartition>topicAndPartitions = new ArrayList<>();
org.apache.kafka.common.TopicPartition topicAndPartition = new org.apache.kafka.common.TopicPartition("my_topic", 0);
topicAndPartitions.add(topicAndPartition);
kafkaConsumer.assign(topicAndPartitions);
kafkaConsumer.seekToEnd(topicAndPartitions);
long lPos = kafkaConsumer.position(topicAndPartition);
Got the same exception (NetworkReceive.readFromReadableChannel) when it got to the .position() call.
Based on the source code, current version for OffsetRequest is 0 not 1. Besides the source code does not return Version-1 response containing timestamp information as doc says. So it might be a doc bug.
If you've come to this point here's a working solution:
private void getOffsets(String topic, String group) {
KafkaConsumer<String, String> kafkaConsumer = getConsumer(topic, group);
List<PartitionInfo> partitionInfos = kafkaConsumer.partitionsFor(topic);
List<org.apache.kafka.common.TopicPartition>topicAndPartitions = new ArrayList<>();
for(int i = 0; i < partitionInfos.size(); i++) {
org.apache.kafka.common.TopicPartition topicAndPartition = new org.apache.kafka.common.TopicPartition(topic, i);
topicAndPartitions.add(topicAndPartition);
}
List<Long>startList = new ArrayList<>();
List<Long>endList = new ArrayList<>();
kafkaConsumer.assign(topicAndPartitions);
for(int i = 0; i < partitionInfos.size(); i++) {
OffsetAndMetadata offsetAndMetadata = kafkaConsumer.committed(topicAndPartitions.get(i));
if(offsetAndMetadata != null) {
startList.add(offsetAndMetadata.offset());
}
}
// did we find any active partitions?
if(startList.size() == 0) {
LOGGER.info("topic:group not found: {}:{}", topic, group);
return;
}
kafkaConsumer.seekToEnd(topicAndPartitions);
for(int i = 0; i < partitionInfos.size(); i++) {
endList.add(i, kafkaConsumer.position(topicAndPartitions.get(i)));
}
LOGGER.debug("startlist.size: {} endlist.size: {} partitions: {}", startList.size(), endList.size(), partitionInfos.size());
long sumLag = 0;
for(int i = 0; i < partitionInfos.size(); i++) {
long lStart = startList.get(i);
long lEnd = endList.get(i);
sumLag += (lEnd - lStart);
/*
* At this point Im sending the info to data dog.
* The 'sum' value is nice to have.
*/
LOGGER.debug("partition: {} start: {} end: {} lag: {}", i, lStart, lEnd, (lEnd - lStart));
}
kafkaConsumer.poll(100);
topicAndPartitions.clear();
kafkaConsumer.assign(topicAndPartitions)
}

Saving Objects from an Iterated List

I'm currently workin' on a sales module using java+hibernate+oracle... I'm done with my order form in my jsp like this:
I'm getting my parameters doing this:
ArrayList<String> idMercaderias = new ArrayList<String>();
ArrayList<String> cantidades = new ArrayList<String>();
ArrayList<String> precios = new ArrayList<String>();
for (int k = 0; k < 10; k++) {
idMercaderias.add(request.getParameter("idMercaderia" + k));
cantidades.add(request.getParameter("cantidad" + k));
precios.add(request.getParameter("precio" + k));
}
I have 10 rows on my order detail, so I made the for, where my inputs are input1, input2, input3, etc. These are attributes of my object Mercaderia so i need to set them up, since they're on lists:
First I'm filtering the first list to avoid repeated articles:
Iterator itra = idMercaderias.listIterator();
ArrayList<String> sortedListIdMercaderias = new ArrayList<String>();
Object m;
while (itra.hasNext()) {
m = itra.next();
if (!sortedListIdMercaderias.contains(m)) {
sortedListIdMercaderias.add((String) m);
}
}
Now I create my object to set all the attributes:
DetallePedido detalle = new DetallePedido();
Now I'm doing a cycle 10 times (thinking of all rows in my form) and start to iterate each list to get my object attributes avoiding null or empty entries.
for (int x = 0; x < sortedListIdMercaderias.size(); x++) {
Iterator itr = idMercaderias.listIterator();
while (itr.hasNext()) {
String mercaderia = (String) itr.next();
if ((mercaderia != null) && (!mercaderia.equals(""))) {
Mercaderia mercaderiaSeleccionada = new MercaderiaDAO().findById(Integer.parseInt(mercaderia));
detalle.setMercaderia(mercaderiaSeleccionada);
}
}
Iterator itr2 = cantidades.listIterator();
while (itr2.hasNext()) {
String cantidad = (String) itr2.next();
if ((cantidad != null) && (!cantidad.equals(""))) {
int cantidadMercaderiaSeleccionada = Integer.parseInt(cantidad);
detalle.setCantidad(cantidadMercaderiaSeleccionada);
}
}
Iterator itr3 = precios.listIterator();
while (itr3.hasNext()) {
String precio = (String) itr3.next();
if ((precio != null) && (!precio.equals(""))) {
BigDecimal precioMercaderiaSeleccionada = new BigDecimal(precio);
detalle.setPrecioUnitario(precioMercaderiaSeleccionada);
}
}
Finally i just persist to my database:
Session session = new DetallePedidoDAO().getSession();
Transaction tx = session.beginTransaction();
try {
session.saveOrUpdate(detalle);
tx.commit();
session.close();
} catch (HibernateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I don't know why in the database i only get 1 row inserted (the last one with valid data) instead of all of them.
Any help will be really apreciated, this is for my final test in university project.
You've only ever got one DetallePedido object. You're changing its field values over and over in the various loops, but it's still just one object. Lastly you're saving it. Just once. Naturally, you only get one row inserted in your database.
What you could try is, instead of iterating through your Mercaderia objects, your Cantidad objects and your Precio objects separately; have a single loop that WITHIN EACH ITERATION creates a new DetallePedido object, sets the Mercaderia, the Cantidada and the Precio, and then saves the DetallePedido.
So, following the clues by David Wallace I made some tweaks to the idea and created an object WrapperDetallePedido like this:
public class WrapperDetallePedido {
int idMercaderia;
int cantidad;
double precio;
public int getIdMercaderia() {
return idMercaderia;
}
public void setIdMercaderia(int idMercaderia) {
this.idMercaderia = idMercaderia;
}
public int getCantidad() {
return cantidad;
}
public void setCantidad(int cantidad) {
this.cantidad = cantidad;
}
public double getPrecio() {
return precio;
}
public void setPrecio(double precio) {
this.precio = precio;
}
}
Then in my Controller I created a single ArrayList and set my DetallePedido attributes:
ArrayList<WrapperDetallePedido> listado = new ArrayList<WrapperDetallePedido>();
for (int k = 0; k < 10; k++) {
if (!request.getParameter("idMercaderia" + k).equals("")){
WrapperDetallePedido WDetallePedido = new WrapperDetallePedido();
WDetallePedido.setIdMercaderia(Integer.parseInt(request.getParameter("idMercaderia" + k)));
WDetallePedido.setCantidad(Integer.parseInt(request.getParameter("cantidad" + k)));
WDetallePedido.setPrecio(Double.parseDouble(request.getParameter("precio" + k)));
listado.add(WDetallePedido);
}
}
Finally used Iterator for the previous list and set all the items from listado and persist to the database:
for (Iterator iterador = listado.listIterator(); iterador.hasNext();) {
WrapperDetallePedido detalle = (WrapperDetallePedido) iterador.next();
Mercaderia mercaderiaSeleccionada = new MercaderiaDAO().findById(detalle.getIdMercaderia());
DetallePedido detallePedido = new DetallePedido();
detallePedido.setMercaderia(mercaderiaSeleccionada);
detallePedido.setCantidad(detalle.getCantidad());
detallePedido.setPrecioUnitario(new BigDecimal(detalle.getPrecio()));
detallePedido.setPedidos(pedidoGenerado);
Session session1 = new DetallePedidoDAO().getSession();
Transaction tx1 = session1.beginTransaction();
new DetallePedidoDAO().save(detallePedido);
try {
session1.saveOrUpdate(detallePedido);
tx1.commit();
session1.close();
} catch (HibernateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Finally got all my rows inserted as i needed... Thank you!

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.

Categories

Resources