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!
Related
i have list of items in cart(assume each letter is an item)
cart list = a,s,d,f,a,s,d,f,a
here is the promotion
buy 1 a and get 2 d Free of Charge(in the below logic 1 is srcNum and 2 is tarNum)
the logic should be progressive.(for each a 2d should be free).
for the above input o/p should be d,d
i made some thing like below. but not working
any help appreciated
Iterator tempIterator = tempList.iterator();
boolean targetCheck = false;
int check=0;
boolean runCompleted = false;
while (!runCompleted && tempIterator.hasNext()){
String itemCode = (String) tempIterator.next();
if(!targetCheck && targetItemsList.contains(itemCode) && check < tarNum){
tempIterator.remove();
check++;
}
else if (check >= tarNum && targetCheck == false) {
check = 0;
targetCheck = true;
}
else if (check < srcNum && targetCheck == true) {
tempIterator.remove();
Integer discountQuantity = discountedItems.get(itemCode);
if(null==discountQuantity) {
discountQuantity = 1;
}else {
discountQuantity++;
}
discountedItems.put(itemCode,discountQuantity);
check++;
}
else if (check >= srcNum && targetCheck == true) {
check = 0;
targetCheck = false;
}
if(tempList.size()==0){
runCompleted = true;
}else{
tempIterator = tempIterator = tempList.iterator();
}
Your discount must be stored: item a has 2 d free. Since java 9 you can use the record class.
record Discount(int itemCode, int free) {};
Map<Integer, Discount> itemCodeToDiscountMap = new HashMap<>();
This becomes a bit more complex if 2 a 1 d free or even 2 a 1 a free. But not unduly.
You have a chaotic cart, something like:
List<Item> cartList = new ArrayList<>();
This is best kept in a map of item code to quantity.
Map<Integer, Integer> itemCodeToQuantityMap = new HashMap<>();
At the end of your evaluation you will have:
Map<Integer, Integer> itemsToPay = new HashSet<>();
Map<Integer, Integer> itemsFree = new HashSet<>();
Map<Integer, Integer> itemsCouldTakeFree = new HashSet<>();
So [a, a, b, d, d, d] with 1a=2d free:
itemsToPay = [a -> 2, b -> 1]
itemsFree = [d -> 3]
itemsCouldTakeFree = [d -> 1] "You can fetch 1 d free"
The first step, simplifying the cart data:
List<Item> cartList = new ArrayList<>();
...
Map<Integer, Integer> itemCodeToQuantityMap = new HashMap<>();
for (Item item: cartList) {
Item oldItem = itemCodeToQuantityMap.get(item.itemCode);
...
itemCodeToQuantityMap.get(item.itemCode, ...);
}
And then
itemsToPay.putAll(itemCodeToQuantityMap);
for (Map.Entry<Integer, Integer> entry: itemCodeToQuantityMap.entrySet()) {
int itemCode = entry.getKey();
int quantity = entry.getValue();
Discount discount = itemCodeToDiscountMap.get(itemCode);
...
}
First making a copy of itemCodeToQuantityMap into itemsToPay means you need not alter itemCodeToQuantityMap but can discount in / subtract from itemsToPay.
As this reeks of home work, I leave it at that. Just the tips:
Use data structures easying the work; here having the quantity of every item.
So one needs a Map.
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.
In class CACallHandler there is a method created by me ie checkCallAllowed. I have taken everything as ConcurrentHashMap and AtomicInteger.
Please ignore the logic of checkCallAllowed but i want to know that if multiple threads will access this method on the same object concurrently, then will it safe.
i dont want to synchronize the entire method as there will be a performce hit.
Requesting your help.
i have executed this method with 30 threads with and without method synchronized, both are giving same result. So want to understand if there will be 200 threads then it will be safe or not.
public class CACallHandler {
public ThrottleCallAlert throttleCallAlert ;
Map<String, TCACriteria> criteriaMap = new HashMap<String, TCACriteria>();
List<TCAListener> listenerList = new LinkedList< TCAListener>();
Map<String, AtomicInteger[]> intervalMap = new ConcurrentHashMap<String, AtomicInteger[]>();
Map<String, AtomicInteger> oddMap = new ConcurrentHashMap<String, AtomicInteger>();
Map<String, AtomicInteger> evenMap = new ConcurrentHashMap<String, AtomicInteger>();
Map<String, List<ThrottleAlarmType> > alarmsRaised = new ConcurrentHashMap<String, List<ThrottleAlarmType>>();
public Map<String, AtomicInteger> getCurrentMap(){
String abc = new SimpleDateFormat("ss").format(new Date());
if(Integer.parseInt(abc) % 2 == 0){
// even map
return evenMap;
}else{
// odd map
return oddMap;
}
}
public String getCriteria(String callingNo, String Origin1, String Origin2){
String criteriaName = "";
for (Map.Entry<String, TCACriteria> entry : criteriaMap.entrySet())
{
TCACriteria criteria = entry.getValue();
if( callingNo.equals(criteria.callingNo) || Origin1.equals(criteria.sipOrigin) || Origin2.equals(criteria.inapOrigin)){
criteriaName = entry.getKey();
return criteriaName;
}
}
return criteriaName;
}
public boolean checkCallAllowed(String calling, String Origin1, String Origin2){
boolean returnFlag = false;
String currentCriteria = getCriteria(calling, Origin1, Origin2); // test
if(!currentCriteria.isEmpty()){
String abc = new SimpleDateFormat("ss").format(new Date());
if(Integer.parseInt(abc) % 2 == 0){
//taking odd map based on seconds
if(oddMap.get(currentCriteria).get() != 0 ){
for(int i=0; i < intervalMap.get(currentCriteria).length; i++){
System.out.println("aaaaa :"+ intervalMap.get(currentCriteria)[i].get());
if(intervalMap.get(currentCriteria)[i].get() == -1 ){
if(oddMap.get(currentCriteria).get() >= throttleCallAlert.getLwm()){
intervalMap.get(currentCriteria)[i].set(oddMap.get(currentCriteria).get());
}else{
if(alarmsRaised.get(currentCriteria) != null && oddMap.get(currentCriteria).get() < throttleCallAlert.getLwm()){
if(alarmsRaised.get(currentCriteria).contains(ThrottleAlarmType.MAJOR)){
System.out.println("ALARM cleared-111##!!---MAJOR-->>>. currentCriteria "+currentCriteria);
listenerList.get(0).alarmCleared(currentCriteria, ThrottleAlarmType.MAJOR);
alarmsRaised.put(currentCriteria, alarmsRaised.get(currentCriteria)).set(2, ThrottleAlarmType.NONE);
}
}
for(int j=0; j < intervalMap.get(currentCriteria).length; j++){
intervalMap.get(currentCriteria)[j] = new AtomicInteger(-1);
}
}
break;
}
if(i == intervalMap.get(currentCriteria).length - 1){
int majorAlarm = 0;
boolean raiseAlarmRequired = true;
System.out.println("array not -1 111");
for(int j=0; j < intervalMap.get(currentCriteria).length; j++){
if(intervalMap.get(currentCriteria)[j].get() < throttleCallAlert.getLwm() ){
raiseAlarmRequired = false;
}
intervalMap.get(currentCriteria)[j] = new AtomicInteger(-1);
}
if(raiseAlarmRequired){
System.out.println("ALARM RAISED--11---->>>. currentCriteria " + currentCriteria);
//start
if(majorAlarm == intervalMap.get(currentCriteria).length ){ // major
if((alarmsRaised.get(currentCriteria) != null && ! alarmsRaised.get(currentCriteria).contains(ThrottleAlarmType.MAJOR))){
returnFlag = false;
alarmsRaised.put(currentCriteria, alarmsRaised.get(currentCriteria)).set(2, ThrottleAlarmType.MAJOR);
listenerList.get(0).alarmRaised(currentCriteria, ThrottleAlarmType.MAJOR);
}
}
//end
}
if(alarmsRaised.get(currentCriteria) != null && oddMap.get(currentCriteria).get() < throttleCallAlert.getLwm()){
if(alarmsRaised.get(currentCriteria).contains(ThrottleAlarmType.WARNING)){
System.out.println("ALARM cleared-111----->>>. currentCriteria "+currentCriteria);
listenerList.get(0).alarmCleared(currentCriteria, ThrottleAlarmType.WARNING);
alarmsRaised.put(currentCriteria, alarmsRaised.get(currentCriteria)).set(0, ThrottleAlarmType.NONE);
}
}
intervalMap.get(currentCriteria)[0].set(oddMap.get(currentCriteria).get());
}
}
oddMap.get(currentCriteria).set(0);
}
// even map
evenMap.get(currentCriteria).incrementAndGet();
}else{
// takeing even map same as odd map mentioned above
}
}
return returnFlag;
}
}
No, your method is not Thread Safe, but your maps are.
The fact that its method is not synchronized makes it asynchronous, but access to Maps is Thread Safe, that is, only one thread can access at a time.
I analyzed your code but I confess that I could not understand her business logic. To improve your performance and make it more secure to threads, I've separated the processing into two methods and made them synchronized. I also made some changes to the code which I commented their reasons.
My biggest difficulty has been to understand the negotiating part (what values can be processed in competition or not) and what can be affected in it, but I believe you can also try to use synchronized blocks, for example in the currentCriteriaValue variable synchronized (currentCriteriaValue ) {...
What could improve was it, I believe that to get better I would have to have the field of negotiation rule.
public class CACallHandler {
//Only one SimpleDateFormat instance is enought to format all dates
private SimpleDateFormat sdfSS = new SimpleDateFormat("ss");
public ThrottleCallAlert throttleCallAlert;
List<TCAListener> listenerList = new LinkedList< TCAListener>();
Map<String, TCACriteria> criteriaMap = new HashMap<String, TCACriteria>();
Map<String, AtomicInteger[]> intervalMap = new ConcurrentHashMap<String, AtomicInteger[]>();
Map<String, AtomicInteger> oddMap = new ConcurrentHashMap<String, AtomicInteger>();
Map<String, AtomicInteger> evenMap = new ConcurrentHashMap<String, AtomicInteger>();
Map<String, List<ThrottleAlarmType> > alarmsRaised = new ConcurrentHashMap<String, List<ThrottleAlarmType>>();
static String[] testeValues = {"callingNo", "sipOrigin", "inapOrigin", "A", "B", "C"};
{//Populates values to test
throttleCallAlert = new ThrottleCallAlert();
criteriaMap.put("callingNo", new TCACriteria());
criteriaMap.put("sipOrigin", new TCACriteria());
criteriaMap.put("inapOrigin", new TCACriteria());
evenMap.put("callingNo", new AtomicInteger(1));
evenMap.put("sipOrigin", new AtomicInteger(2));
evenMap.put("inapOrigin", new AtomicInteger(3));
oddMap.put("callingNo", new AtomicInteger(1));
oddMap.put("sipOrigin", new AtomicInteger(2));
oddMap.put("inapOrigin", new AtomicInteger(3));
intervalMap.put("callingNo", new AtomicInteger[] { new AtomicInteger(1), new AtomicInteger(2), new AtomicInteger(3) });
intervalMap.put("sipOrigin", new AtomicInteger[] { new AtomicInteger(1), new AtomicInteger(2), new AtomicInteger(3) });
intervalMap.put("inapOrigin", new AtomicInteger[] { new AtomicInteger(1), new AtomicInteger(2), new AtomicInteger(3) });
}
public static void main(String[] args) throws InterruptedException {
CACallHandler handler = new CACallHandler();
int threads = 10000;
ExecutorService taskExecutor = Executors.newFixedThreadPool( threads );
//Thread.sleep(12000);
Date startTime = new Date();
for( int i = 0 ; i < threads; i++ ) {
int i1 = ThreadLocalRandom.current().nextInt(0, 5 + 1);
int i2 = ThreadLocalRandom.current().nextInt(0, 5 + 1);
int i3 = ThreadLocalRandom.current().nextInt(0, 5 + 1);
taskExecutor.execute( new Thread(){ public void run() {handler.checkCallAllowed(testeValues[i1], testeValues[i2], testeValues[i3]);} } );
}
taskExecutor.shutdown();
taskExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
Date finishTime = new Date();
System.out.println( "Execution time in ms: " + (finishTime.getTime() - startTime.getTime()) );
}
/**
* Return the odd or even map based on current time
* #return Map
*/
public Map<String, AtomicInteger> getCurrentMap(){
switch( getCurrentMapType() ) {
case EVEN: return evenMap;
case ODD: return oddMap;
default: return null;
}
}
/**
* Check if criteriaMap has the [callingNo | Origin1 | Origin2] passed
* #param callingNo -
* #param Origin1
* #param Origin2
* #return String - the criteriaMap key equals to parameter or empty string
*/
public String getCriteria(String callingNo, String Origin1, String Origin2){
for (Map.Entry<String, TCACriteria> entry : criteriaMap.entrySet()){
TCACriteria criteria = entry.getValue();
if( callingNo.equals(criteria.callingNo) || Origin1.equals(criteria.sipOrigin) || Origin2.equals(criteria.inapOrigin))
return entry.getKey();
}
return null;
}
/**
* get odd map type based on seconds
* #return MapType
*/
private MapType getCurrentMapType() {
return MapType.EVEN;//No odd implementation
/*if(Integer.parseInt( sdfSS.format(new Date()) ) % 2 == 0){
return MapType.EVEN;
}else{
return MapType.ODD;
}*/
}
/**
* Get the currente criteria based on parameters then process it
* #param calling
* #param Origin1
* #param Origin2
* #return
*/
public boolean checkCallAllowed(String calling, String Origin1, String Origin2){
String currentCriteria = getCriteria(calling, Origin1, Origin2);
if( currentCriteria != null ){
switch( getCurrentMapType() ) {
case EVEN: return proccessEvenMapType(currentCriteria);
case ODD: return proccessOddMapType(currentCriteria);
default: return false; //TODO check it
}
}
return false;
}
/**
* Process currentcriteria based on even Map
* #param currentCriteria
* #return boolean - always false??
*/
private synchronized boolean proccessEvenMapType( String currentCriteria ) {
boolean returnFlag = false; //TODO this variable never receivs true..??
//Only one call to map, reduce the time on searching and processing
Integer currentCriteriaValue = oddMap.get(currentCriteria).get();
if(currentCriteriaValue != 0 ){
//Only one call to map, reduce the time on searching and processing
AtomicInteger[] intervalArray = intervalMap.get(currentCriteria);
for(int intervalIndex=0; intervalIndex < intervalArray.length; intervalIndex++){
AtomicInteger currentInterval = intervalArray[intervalIndex];
System.out.println("aaaaa :"+ currentInterval.get());
if(currentInterval.get() == -1 ){
if(currentCriteriaValue >= throttleCallAlert.getLwm()){
currentInterval.set(currentCriteriaValue);
}else{
List<ThrottleAlarmType> alarmTypeList = alarmsRaised.get(currentCriteria) ;
if(alarmTypeList != null && currentCriteriaValue < throttleCallAlert.getLwm()){
if(alarmTypeList.contains(ThrottleAlarmType.MAJOR)){
System.out.println("ALARM cleared-111##!!---MAJOR-->>>. currentCriteria "+currentCriteria);
listenerList.get(0).alarmCleared(currentCriteria, ThrottleAlarmType.MAJOR);
alarmsRaised.put(currentCriteria, alarmTypeList).set(2, ThrottleAlarmType.NONE);
}
}
for(int j=0; j < intervalArray.length; j++){
intervalArray[j] = new AtomicInteger(-1);
}
}
break;
}
if(intervalIndex == intervalArray.length - 1){
int majorAlarm = 0;
boolean raiseAlarmRequired = true;
System.out.println("array not -1 111");
for(int j=0; j < intervalArray.length; j++){
if(intervalArray[j].get() < throttleCallAlert.getLwm() ){
raiseAlarmRequired = false;
}
intervalArray[j] = new AtomicInteger(-1);
}
if(raiseAlarmRequired){
System.out.println("ALARM RAISED--11---->>>. currentCriteria " + currentCriteria);
//start
if(majorAlarm == intervalArray.length ){ // major
if((alarmsRaised.get(currentCriteria) != null && ! alarmsRaised.get(currentCriteria).contains(ThrottleAlarmType.MAJOR))){
returnFlag = false;
alarmsRaised.put(currentCriteria, alarmsRaised.get(currentCriteria)).set(2, ThrottleAlarmType.MAJOR);
listenerList.get(0).alarmRaised(currentCriteria, ThrottleAlarmType.MAJOR);
}
}
//end
}
if(alarmsRaised.get(currentCriteria) != null && currentCriteriaValue < throttleCallAlert.getLwm()){
if(alarmsRaised.get(currentCriteria).contains(ThrottleAlarmType.WARNING)){
System.out.println("ALARM cleared-111----->>>. currentCriteria "+currentCriteria);
listenerList.get(0).alarmCleared(currentCriteria, ThrottleAlarmType.WARNING);
alarmsRaised.put(currentCriteria, alarmsRaised.get(currentCriteria)).set(0, ThrottleAlarmType.NONE);
}
}
intervalArray[0].set(currentCriteriaValue);
}
}
oddMap.get(currentCriteria).set(0);
}
// even map
evenMap.get(currentCriteria).incrementAndGet();
return returnFlag;
}
private boolean proccessOddMapType( String currentCriteria ) {
System.out.println("proccessOddMapType Not implemented yet!!");
return false;
}
}
enum MapType{
ODD, EVEN;
}
I have to preprocess 4 lists of medical data before we can import it into the software.
I have given 4 lists, each ordered already, that look like the following:
File 1) chapter
A00-B99;
C00-D48;
D50-D89;
C00-C99;
E00-E90;
...
Z00-Z99;
File 2) subchapter
A00-A09;
A15-A19;
A92-A99;
B95-B98;
B99-B99;
C00-C48;
...
Z80-Z99;
File 3) Groups
A00.-
A01.-
A02.-
...
C01.-
....
Z99.-
File 4) diagnoses
A00.0;
A00.1;
A00.7;
A00.8;
A01.7;
A02.8;
..
Z00.3;
Z00.4;
;
At the End it shoud be ordered as the list below.
Each line will be a line within a csv-file.
A00-B99; (Chapter)
A00-A09; (Subchapter)
A00.- (corresponding group)
A00.0 (corresponding diagnoses)
A00.1
A00.7
A00.8
A01.- (corresponding group)
A01.7 (corresponding diagnoses)
A02.- (corresponding group)
A02.8 (corresponding diagnoses)
...
B15-B99(Subchapter)
...
C00-C99 (Chapter)
C00-D48 (Subchapter)
C01.- (corresponding group)
C01.2 (corresponding diagnoses)
I've tried it so far by using some linked hasmaps but don't get the correct result.
while (entries_kapitel.hasNext()) {
Entry thisEntry_kapitel = (Entry) entries_kapitel.next();
String key_kapitel = (String) thisEntry_kapitel.getKey();
String text_kapitel = (String) thisEntry_kapitel.getValue();
// A00-B99 -> A und B
String kapitel_char1 = key_kapitel.split("-")[0].substring(0, 1);
String kapitel_char2 = key_kapitel.split("-")[1].substring(0, 1);
// A00-B99 -> 99
int kapitel_int2 = Integer.parseInt(key_kapitel.split("-")[1].substring(1, 3));
// subchapters
while (entries_gruppen.hasNext()) {
Entry thisEntry_gruppen = (Entry) entries_gruppen.next();
String key_gruppen = (String) thisEntry_gruppen.getKey();
String text_gruppen = (String) thisEntry_gruppen.getValue();
// Gruppe splitten T90-T89
String gruppe_char1 = key_gruppen.split("-")[0].substring(0, 1);
String gruppe_char2 = key_gruppen.split("-")[1].substring(0, 1);
int gruppe_int2 = Integer.parseInt(key_gruppen.split("-")[1].substring(1, 3));
if (gruppe_char1.equals(gruppe_char2) == false){
System.err.println("Subchapters start with the same capital!");
System.exit(1);
}
while (entries_gruppierung.hasNext()) {
Entry thisEntry_gruppierung = (Entry) entries_gruppierung.next();
String key_gruppierung = (String) thisEntry_gruppierung.getKey();
String text_gruppierung = (String) thisEntry_gruppierung.getValue();
String gruppierung_char1 = key_gruppierung.substring(0, 1);
int gruppierung_int1 = Integer.parseInt(key_gruppierung.substring(1, 3));
(gruppierung_char1.equals(gruppe_char1) && gruppierung_int1 <= gruppe_int2) {
System.out.println("Chapter: " + key_kapitel + " subchapter: " + key_gruppen + " group" + key_gruppierung);
while (diagnoses.hasNext()) {
....
The result does not look like it should (there are missing entries and they are not all ordered correctly)
What is the best way to solve this task?
I was not able to get a working tree, which probably is the best way to go, right?
If I understod well you're needs. I would use a SORT / MERGE join approach. Consider 4 lists containing the entries, properly sorted. Then you can merge the lists by scanning them alternately. I haven't tested the code but you'll get the general idea :
public class EntryComparator implements Comparator<Entry>
{
public boolean isSubsection(Entry e1, Entry e2)
{
// should return true if e2 subsection of e1
}
public int compare(Entry e1, Entry e2)
{
// see the Comparator interface documentation
}
}
List<Entry> chapters = new ArrayList<>();
List<Entry> subchapters = new ArrayList<>();
List<Entry> groups = new ArrayList<>();
List<Entry> diagnoses = new ArrayList<>();
List<Entry> result = new ArrayList<>(); // will hold the final result
// populate the lists, maybe sort them using Collections.sort and the Comparator above
int i1 = 0;
int i2 = 0;
int i3 = 0;
int i4 = 0;
EntryComparator c = new EntryComparator();
while( i1 < chapters.size() )
{
result.add(chapters.get(i1));
while( i2 < subchapters.size() &&
c.isSubsection(chapters.get(i1), subchapters.get(i2)) )
{
result.add(subchapters.get(i2));
while( i3 < groups.size() &&
c.isSubsection(subchapters.get(i2), groups.get(i3)) )
{
result.add(groups.get(i3));
while( i4 < subchapters.size() &&
c.isSubsection(groups.get(i3), diagnoses.get(i4)) )
{
result.add(diagnoses.get(i4));
i4++;
}
i3++;
}
i2++;
}
i1++;
}
EDIT : the advice given by 911DidBush is a good one, you may apply the same pattern with specialized classes.
thanks for your replies. As recommended, I will implement each list as a Class. This seems a really good idea. The Class Chapter will look like this. The other classes are having the same structure as well.
public class Chapter {
private String key_chapter;
private String text;
private ArrayList<Subchapter> subchapters = new ArrayList<>();
public Chapter(String chapter, String text) {
this.key_chapter = chapter;
this.text = text;
subchapters = new ArrayList<Subchapter>();
}
public String getChapter() {
return key_chapter;
}
public String getText() {
return text;
}
public void addSubchapter(String subchapter, String text) {
subchapters.add(new Subchapter(subchapter, text));
}
public Subchapter getKeyAtIndex(int index) {
return subchapters.get(index);
}
// get the entire ArrayList:
public ArrayList getListOfSubchapters() {
return subchapters;
}
}
I am reading a CSV and mapping it to a List<SomeBean> using ICsvBeanReader.
csv:
someName,someNumber,report,env,dir
TEST1,111111111111,DES,T,LAS
TEST1,111111111111,INV,T,LAS
TEST1,111111111111,DES,T,FIRS
TEST1,111111111111,INV,T,FIRS
TEST1,111111111111,ORD,P,FIRS
TEST1,111111111111,ORD,P,LAS
Once I have the List<SomeBean> dataList, I am running nested for loop to get what I am intended to achieve.
Defined Order:
{1-FIRS, 2-LAS}
{1-P, 2-T}
{1-ORD, 2-DES, 3-INV}
Expected:
A map of 'someNumber' and combination of report,env,dir (In a defined Orders).
111111111111,ORD-P-FIRS
111111111111,DES-T-FIRS
111111111111,INV-T-FIRS
111111111111,ORD-P-LAS
111111111111,DES-T-LAS
111111111111,INV-T-LAS
CODING:
Get Order:
Map<Integer, String> dirOrder = {1-FIRS, 2-LAS}; // getting from defined config
Map<Integer, String> envOrder = {1-P, 2-T}; // getting from defined config
Map<Integer, String> reportOrder = {1-ORD, 2-DES, 3-INV};// getting from defined config
Run loops for preparing map:
MultiValuedMap < String, String > mapProperOrder = new ArrayListValuedHashMap < > ();
for (Map.Entry < Integer, String > directionEntry: dirOrder.entrySet()) {
String directionValue = directionEntry.getValue();
for (Map.Entry < Integer, String > envirionmentEntry: envOrder.entrySet()) {
String envirionmentValue = envirionmentEntry.getValue();
for (Map.Entry < Integer, String > reportTypeEntry: reportOrder.entrySet()) {
String reportTypeValue = reportTypeEntry.getValue();
for (SomeBean someBean: (List < SomeBean > ) someList) {
String num = someBean.getNum();
String dir = someBean.getDir();
String env = someBean.getEnv();
String report = someBean.getReport);
boolean directionCheck = dir.equalsIgnoreCase(directionValue) ? true : false;
boolean envirionmentCheck = env.equalsIgnoreCase(envirionmentValue) ? true : false;
boolean reportTypeCheck = report.equalsIgnoreCase(reportTypeValue) ? true : false;
if (directionCheck && envirionmentCheck && reportTypeCheck) {
mapProperOrder.put(num, report + "-" + env + "-" + dir);
}
}
}
}
}
This code does its job, but what if I have a multiple 'someNumber' in a CSV, It will be not efficient to run a nested for loop for all the records.
Please help me to write a simple yet efficient way to process this.
I personally would implement Comparable interface in SomeBean if this order is default order application-wide or a custom Comparator otherwise.
The implementation might look as it follows:
public int compare(SomeBean o1, SomeBean o2) {
Map<String, Integer> firstLevel = new HashMap<>();
firstLevel.put("FIRS", 1);
firstLevel.put("LAS", 2);
int cmp = firstLevel.get(o1.getDir()).compareTo(firstLevel.get(o2.getDir()));
if (cmp != 0) {
return cmp;
}
Map<String, Integer> secondLevel = new HashMap<>();
secondLevel.put("P", 1);
secondLevel.put("T", 2);
cmp = secondLevel.get(o1.getEnv()).compareTo(secondLevel.get(o2.getEnv()));
if (cmp != 0) {
return cmp;
}
Map<String, Integer> thirdLevel = new HashMap<>();
thirdLevel.put("ORD", 1);
thirdLevel.put("DES", 2);
thirdLevel.put("INV", 3);
return thirdLevel.get(o1.getReport()).compareTo(thirdLevel.get(o2.getReport()));
}