Map key value pair in java not getting properly - java

i am using Map for inserting some objects, while puting object its working fine ,
but while iterating same map i m getting the size of object as correctly, but i m gettting only
last object,in all the iteration , for ur reference i am pasting all the code as follows,
package map;
Map<Integer,ListLabcar> ma = new LinkedHashMap<Integer,ListLabcar>();
ListLabcar lc = new ListLabcar();
for(int l =0;l<5;l++){
int j = 0;
for(int i = 0;i<=3;i++){
if(i==l){
System.out.println("ok");
j+=1;
lc.setIn(j);
lc.setS("a-"+l);break;
}
else{
lc.setIn(l);
lc.setS("zero-"+l);
//break;
}
}
ma.put(l, lc);
System.out.println(ma.get(l).getIn());
System.out.println(ma.get(l).getS());
}System.out.println(ma.size());
Set<Integer> ke = ma.keySet();
for(Integer k:ke){
System.out.println(k);
System.out.println("int--->"+ma.get(k).getIn());
System.out.println("sttr--->"+ma.get(k).getS());
}
}
}

This line need to be in the first for loop.
ListLabcar lc = new ListLabcar();
What you are doing is rewriting the values and not adding new objects in the map.
EDIT :
package map;
Map<Integer,ListLabcar> ma = new LinkedHashMap<Integer,ListLabcar>();
for(int l =0;l<5;l++){
ListLabcar lc = new ListLabcar();
int j = 0;
for(int i = 0;i<=3;i++){
if(i==l){
System.out.println("ok");
j+=1;
lc.setIn(j);
lc.setS("a-"+l);break;
}
else{
lc.setIn(l);
lc.setS("zero-"+l);
//break;
}
}
ma.put(l, lc);
System.out.println(ma.get(l).getIn());
System.out.println(ma.get(l).getS());
}
System.out.println(ma.size());
Set<Integer> ke = ma.keySet();
for(Integer k:ke){
System.out.println(k);
System.out.println("int--->"+ma.get(k).getIn());
System.out.println("sttr--->"+ma.get(k).getS());
}
}

Related

Simple weighted Graph: Loops not allowed exception

I'm attempting to create a programme which tracks the emails of people. I am using a string for the vertex in my graph (The string is their email) and a DefaultWeightedEdge from Jgrapht. If these people send one email between each other then the weight of the edge connecting that node is set to 1. If they send another email after already having sent one I increment the edge weight by 1.
I think I have the main bulk of the code correct, however I am getting this exception.
Exception in thread "main" java.lang.IllegalArgumentException: loops
not allowed at
org.jgrapht.graph.AbstractBaseGraph.addEdge(AbstractBaseGraph.java:203)
at groupProject.Analysis.StoreEmails(Analysis.java:58) at
groupProject.AnalyserRun.main(AnalyserRun.java:7)
Here is my code:
public class Analysis {
SimpleWeightedGraph<String, DefaultWeightedEdge> graph = new SimpleWeightedGraph<String, DefaultWeightedEdge>(DefaultWeightedEdge.class);
jsonParser jP = new jsonParser("/Users/Kieran/test/test2.json");
int numEmails = jP.getNumEmails();
ArrayList<String> senders = new ArrayList<String>();
ArrayList<String> recipients = new ArrayList<String>();
ArrayList<String> all = senders;
ArrayList<DefaultWeightedEdge> edges = new ArrayList<DefaultWeightedEdge>();
public void StoreEmails(){
//Creates vertex's for every sender
for(int i = 0; i < numEmails; i++){
Email email = jP.parseJSON(i);
if(!senders.contains(email.getSender())){
graph.addVertex(email.getSender());
senders.add(email.getSender());
}
}
//creates vertex's for every recipient
for(int i = 0; i < numEmails; i++){
Email email = jP.parseJSON(i);
if(email.getRecipients().length != 0){
for(int j = 0; j < email.getRecipients().length; j++){
if(!recipients.contains(email.getRecipients()[j])){
graph.addVertex(email.getRecipients()[j]);
recipients.add(email.getRecipients()[j]);
}
}
}
}
all.removeAll(recipients);
all.addAll(recipients);
/*
* Adds all of the edges from senders to recipients and if the edge already exists then it will increase the weight by one
* however is is a directed graph so you need to check both pairs.
*/
for(int j = 0; j < numEmails; j++){
Email email = jP.parseJSON(j);
for(int k = 0; k < email.getRecipients().length; k++){
if(graph.containsEdge(email.getSender(), email.getRecipients()[k])){
int current_weight = (int) graph.getEdgeWeight(graph.getEdge(email.getSender(), email.getRecipients()[k]));
graph.setEdgeWeight(graph.getEdge(email.getSender(), email.getRecipients()[k]), current_weight+1);
}else{
DefaultWeightedEdge e = graph.addEdge(email.getSender(), email.getRecipients()[k]);
graph.setEdgeWeight(e, 1);
}
}
}
builder();
}
public int calcConnectedness(String s1,String s2){
int connectedness = 0;
int weightS1S2 = 0;
int weightS2S1 = 0;
if(graph.containsEdge(s1, s2)){
weightS1S2 = (int) graph.getEdgeWeight(graph.getEdge(s1, s2));
connectedness += weightS1S2;
}
/*if(graph.containsEdge(s2, s1)){
weightS2S1 = (int) graph.getEdgeWeight(graph.getEdge(s2, s1));
connectedness += weightS2S1;
}*/
return connectedness;
}
public void builder(){
for(int i = 0; i < all.size(); i++){
for(int j = i+1; j < all.size(); j++){
if(graph.containsEdge(all.get(i), all.get(j)))
make(all.get(i), all.get(j), calcConnectedness(all.get(i), all.get(j)));
}
}
}
public void make(String user1, String user2, int connectedness){
System.out.println(user1 + " " + user2 + " Are connected by a factor of: "+connectedness);
}
}
After some research the only information I was able to find which may be causing the problem is the fact that in Java, strings are immutable. However, I was still not able to resolve my issues.
The answer was in this section of code:
}else{
DefaultWeightedEdge e = graph.addEdge(email.getSender(), email.getRecipients()[k]);
graph.setEdgeWeight(e, 1);
}
It turns out that email.getSender() was in email.getRecipients() so the source and destination of the edge was the same i.e a loop. I solved the issue by doing a simple check beforehand with an if statement to only add an edge if it was not the same as the source.

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!

Iterator removal/edit is safe, however I also need to edit all following Iterations

I have read a little about ConcurrentModificationException in stackflow and my actual update appears not to be the issue, it could be a problem in my design or I need a technique I haven't learnt yet.
Example Situation:
My iterator is running along position markers.
Then an action can be performed to shift the markers over (e.g. Inserting into string).
All Markers greater than the current position must also be shifted to preserve correctness.
Task:
How do I update the remaining markers without the iterator exploding?
Can I refresh the iterator, or break and start the loop again?
The following code is abstracted from my work.
public void innerLoop(Boolean b) {
//An Example of what I'm working with
HashMap<String, HashSet<Integer>> map = new HashMap<String, HashSet<Integer>>() {
{
put("Nonce",
new HashSet<Integer>() {
{
add(1);
add(2);
add(3);
add(4);
add(5);
}
});
}
};
//for each key
for (String key: map.keySet()) {
HashSet<Integer> positions = map.get(key);
//for each integer
for (Iterator<Integer> it = positions.iterator(); it.hasNext();) {
Integer position = it.next();
System.out.println("position =" + position);
//(out of scope) decision requiring elements from the outter loops
if (new Random().nextBoolean()&&b) {
//shift position by +4 (or whatever)
//and every other (int >= position)
System.out.println("Shift " + position + " by 4");
Integer shift = 4;
update(position,
shift,
positions);
it.remove();
}
}
}
}
public void update(Integer current,
Integer diff,
Set<Integer> set) {
if (set != null) {
HashSet<Integer> temp = new HashSet<Integer>();
for (Integer old: set) {
if (old >= current) {
temp.add(old);
System.out.println(old + "Added to temp");
}
}
for (Integer old: temp) {
set.remove(old);
System.out.println(old + "removed");
set.add(old + diff);
System.out.println((old + diff) + "Added");
}
}
}
Edited with Garrett Hall Solution
public void nestedloops() {
HashMap<String, HashSet<Integer>> map = new HashMap<String, HashSet<Integer>>() {
{
put("Hello",
new HashSet<Integer>() {
{
add(5);
add(2);
add(3);
add(4);
add(1);
add(6);
}
});
}
};
//for each key
for (String key: map.keySet()) {
ArrayList<Integer> positions = new ArrayList<Integer>(map.get(key));
//for each integer
for (int i = 0; i < positions.size(); i++) {
Integer position = positions.get(i);
System.out.println("[" + i + "] =" + position);
//out of scope decision
if (new Random().nextBoolean()) {
//shift position by +4
//and every other (int >= position)
System.out.println("Shift after " + position + " by 4");
Integer shift = 4;
//Update the array
for (int j = 0; j < positions.size(); j++) {
Integer checkPosition = positions.get(j);
if (checkPosition > position) {
System.out.println(checkPosition + "increased by 4");
positions.set(j,
checkPosition + shift);
}
}
}
}
//Add updated Array
map.put(key,
new HashSet<Integer>(positions));
}
}
You best bet is indexing the HashSet by putting it into a list. Then you can use indices to refer to elements rather than an Iterator. So long as you are not removing or adding (only updating) elements, then your indices will be correct. Otherwise you will have to account for that. Example:
ArrayList<Integer> positions = new ArrayList<Integer>(map.get(key));
for (int i = 0; i < positions.size(); i ++) {
// updating list
for (int j = i; i < positions.size(); j ++) {
positions.set(j, positions.get(i) + diff);
}
}
I would copy the original set to a list so that you don't need to worry about the current iteration code. Then update a secondary list (not being iterated).
Reasons:
You can't iterate and modify your original collection at once (there is no way around the ConcurrentModificationExceptions)
Nice one liner to shift items in a list.
Collections.rotate(list.subList(j, k+1), -1);
Guava will be able to handle the "find first index that satisfies that predicate and transform the list" which a bunch of utility methods.

Android: HashMap sort by 3 values

I want to sort some data. At the moment the data is stored in a map. I know, I can't sort data in a map by value. I calculate a soccer schedule like that:
TeamName, G+, G-, P
I want to sort first by P, then by G+, then by G-.
Every k,v is in a map like this:
map.put(e.getString("team_id"), 0);
map.put(e.getString("team_id")+"G+", 0);
map.put(e.getString("team_id")+"G-", 0);
I know that the data structure is really bad! I think it is better to get the values into a Collection to do a collection.sort. But How can I do that?
Here is my code (the code works fine, but is unsorted and badly coded):
HashMap<String, Integer> map = new HashMap<String, Integer>();
HashMap<String, String> tab = new HashMap<String, String>();
for(int i=0; i<teams.length(); i++){
JSONObject e = teams.getJSONObject(i);
//get TeamID
map.put(e.getString("team_id"), 0);
//Goals +
map.put(e.getString("team_id")+"G+", 0);
//Goals -
map.put(e.getString("team_id")+"G-", 0);
//standings.add(map);
//Log.e("Team7", String.valueOf(map.get("7")));
//Log.e("Team7", e.getString("team_id"));
}
for(int i=0; i<matchdata.length(); i++){
JSONObject e = matchdata.getJSONObject(i);
//calculate Points
int myVarGoal1 = Integer.valueOf(e.getString("points_team1"));
int myVarGoal2 = Integer.valueOf(e.getString("points_team2"));
if ((myVarGoal1) > (myVarGoal2)){
myPoint1 = 3;
myPoint2 = 0;
}
if ((myVarGoal1) < (myVarGoal2)){
myPoint1 = 0;
myPoint2 = 3;
}
if ((myVarGoal1) == (myVarGoal2)){
myPoint1 = 1;
myPoint2 = 1;
}
int calc1 = (map.get(e.getString("id_team1")) + myPoint1);
int calc2 = (map.get(e.getString("id_team2")) + myPoint2);
map.put("id", Integer.valueOf(i));
map.put(e.getString("id_team1"), calc1);
map.put(e.getString("id_team2"), calc2);
//calculate Goals
int calcGoal1 = (map.get(e.getString("id_team1")+"G+") + myVarGoal1);
int calcGoal2 = (map.get(e.getString("id_team1")+"G-") + myVarGoal2);
int calcGoal3 = (map.get(e.getString("id_team2")+"G+") + myVarGoal2);
int calcGoal4 = (map.get(e.getString("id_team2")+"G-") + myVarGoal1);
map.put(e.getString("id_team1")+"G+", calcGoal1);
map.put(e.getString("id_team1")+"G-", calcGoal2);
map.put(e.getString("id_team2")+"G+", calcGoal3);
map.put(e.getString("id_team2")+"G-", calcGoal4);
//standings.add(map);
//Log.e("TeamID", e.getString("id_team1"));
//Log.e("PointsTeam7", String.valueOf(map.get("7")));
//Log.e("GaolsTeam7", String.valueOf(map.get("7G-")));
}
for(int i=0; i<teams.length(); i++){
JSONObject e = teams.getJSONObject(i);
String myTeamID = e.getString("team_id");
int Gdif = (map.get(myTeamID+"G+")) - (map.get(myTeamID+"G-"));
tab.put(myTeamID, e.getString("team_name") +","+ map.get(myTeamID) +","+ (map.get(myTeamID+"G+")) +":"+ (map.get(myTeamID+"G-")) +" "+ Gdif);
//Log.e("Team7", String.valueOf(tab.get("7")));
//Log.e("Team7", e.getString("team_id"));
strGoals+="\n" + String.valueOf(tab.get(myTeamID));
}
It sounds like you need to first create your own class to hold related data as one single object. The exact name of the class depends on what the data is. Maybe SoccerTeam or SoccerSchedule. After you create this class, you can implement the Comparable interface or create a Comparator object that defines the sorting order.
I think what you're looking for is a TreeMap and a Comparator. Can you switch to using a TreeMap instead? It works just like a HashMap, but will automatically sort your keys for you. Then you can use a Comparator like this:
Map<String, Integer> map = new HashMap<String, Integer>();
..... do stuff .....
TreeMap<String, Integer> treeMap = new TreeMap<String, Integer>(new Comparator<String>()
{
#Override
public int compare(String lhs, String rhs)
{
// return 1 if lhs > rhs
// return 0 if lhs = rhs
// return -1 if lhs < rhs
if (lhs == null && rhs == null) return 0;
if (lhs == null) return -1;
if (rhs == null) return 1;
if ((lhs.endsWith("P") && (rhs.endsWith("P")))
|| (lhs.endsWith("G+") && (rhs.endsWith("G+")))
|| (lhs.endsWith("G-") && (rhs.endsWith("G-"))))
{
return lhs.compareTo(rhs);
}
else if (lhs.endsWith("P"))
{
return -1;
}
else if (rhs.endsWith("P"))
{
return 1;
}
else
{
String lastLeftChar = lhs.substring(lhs.length()-1);
String lastRightChar = rhs.substring(rhs.length()-1);
return lastLeftChar.compareTo(lastRightChar);
}
}
});
treeMap.putAll(map);
// Now your treeMap is sorted by the keys!

How to fill an array with while loop?

I've a piece of code something like this and I want to insert the data by using a while.
Weather weather_data[] = new Weather[]{
new Weather(0, "Cloudy"),
new Weather(0, "Showers"),
new Weather(0, "Snow"),
new Weather(0, "Storm"),
new Weather(0, "Sunny")
};
How can I fill this list using a while ?
Thanks
Try this:
Weather weather_data[] = new Weather[5];
int i = 0;
while(i < weather_data.length){
//fill array [i]
i++;
}
I understand that you want to fill your array with the following String array as base:
String[] weatherTypes = {"Cloudy","Showers","Snow","Storm","Sunny"};
Then you can do this:
int i=0;
Weather[] weather_data = new Weather[];
for (String weatherType: weatherTypes){
weather_data[i] = new Weather(0,weatherType);
i++;
}
You could use also use a list:
List<Weather> weather_data = new ArrayList<Weather>();
for (String weatherType: weatherTypes){
weather_data.add(new Weather(0,weatherTypes));
}
Weather[] weather_data = new Weather[5];
public void addWeatherData(Weather newWeather) {
int counter = 0;
while (counter < weather_data.length) {
if (weather_data[counter] == null) {
weather_data[counter] = newWeather;
return;
}
counter++;
}
}

Categories

Resources