Duplicate elements in ArrayList - java

I have two array list, One is to save name and other is to save quantity. I want to avoid duplicate in the array list. Name array list contains name and its corresponding quantity is contained in quantity array list.
My array list can contains duplicate names, I want to traverse array list to check the name if already exists, if it exists then add the quantity to the previous value and delete duplicate entry.
Eg
Name Quantity
ABC 20
xyz 10
ABC 15
Output Required
Name Quantity
ABC 35
XYZ 10
Thanks

You should use a Map instead, which will not allow for duplicate entries. You use it something like this:
Map<String, Integer> nameToQuantityMap = new HashMap<String, Integer>():
nameToQuantityMap.put("Mr Smith", 100);
nameToQuantityMap.put("Mrs Jones", 500);
EDIT: Now that you've edited the question, the answer is different. If you want to add the values of duplicate keys, you'll have to do something like this:
// For each (name, quantity) pair
if (nameToQuantityMap.containsKey(name) ) {
Integer sum = nameToQuantityMap.get(name) + quantity;
nameToQuantityMap.put(name, sum);
}
else {
nameToQuantityMap.put(name, quantity);
}

I want to avoid duplicate in the array list.
In that case use HashSet
Or else if you have 2 parallel ArrayList then you can use HashMap

The structure you attempt to represent resembles something that should be represented by a Map, which is a key -> value storage type of structure. Having two lists and trying to keep the in sync is a bad idea.

Use java.util.Map where key would be you map and value would be value.
Map<String,Integer> map = new HashMap<>();
if(map.get(name)!=null){
Integer oValue = map.get(name)+nNalue;
}else
map.put(name,value);

Try this if you want to add value to the previous value if Key already exists .
public class Example {
static Map<String, Integer> map = new HashMap<String, Integer>();
public static void main(String[] args) {
insertNameAndQuantity("A", 10);
insertNameAndQuantity("B", 25);
insertNameAndQuantity("A", 25);
System.out.println(map);
}
public static void insertNameAndQuantity(String key, Integer value) {
Integer count = map.get(key);
if (count == null)
map.put(key, value);
else
map.put(key, count + value);
}
}
Output:
{A=35, B=25}

this is an example implement on c# code.
public class temp
{
[Test]
public void T()
{
var list1 = new ArrayList(){"ABC", "xyz", "ABC"};
var list2 = new ArrayList() {20, 10, 15};
var nameList = new List<string>();
var list1result = new ArrayList();
var list2result = new ArrayList();
int index = 0;
foreach (string name in list1)
{
if (!nameList.Contains(name))
{
list1result.Add(name);
var quantity = list2[index] ?? 0;
list2result.Add(quantity);
nameList.Add(name);
}
else
{
var index2 = 0;
foreach (string name2 in list1result)
{
if (name2 == name)
{
list2result[index2] = (int)list2result[index2] + (int)list2[index];
}
index2++;
}
}
index++;
}
Assert.True(list1result.Count == 2, list1result.Count + " t1");
}
}
I've tested the output, it's correct.

Related

Updating a HashMap in such a way that the 2nd value becomes 1st and 3rd becomes 2nd and so on

I have an object with 5 fields as Strings named String1 to String5.
When I remove String1 from the object, I have to update the values such that String1 will have String2 value and so on and String5 will become null.
Say we have a HashMap as below,
HashMap<Integer,String>
It has 5 values. Keys 1 to 5 and corresponding String values.
Now if we have to remove the 1st value such that the 2nd value will become the 1st and 3rd will become 2nd and so on.
How can we achieve this ?
eg: HashMap has
(1,"Art")
(2,"Math")
(3,"Science")
(4,"History")
(5,"Physics")
Now I have to delete the 1st value, then the HashMap will be
(1,"Math")
(2,"Science")
(3,"History")
(4,"Physics")
(5,null)
If I have to delete the 2nd value, then the 1st one will remain the same, but the lower order will be change as follows
(1,"Art")
(2,"Science")
(3,"History")
(4,"Physics")
(5,null)
As mentioned in the comments, you might be better off using a List<String>
private static List<String> removeTopic(List<String> topics, String topic) {
List<String> topicsCopy = new ArrayList<>(topics);
topicsCopy.remove(topic);
topicsCopy.add(null);
return topicsCopy;
}
Then:
List<String> topics = Arrays.asList("Art", "Math", "Science", "History", "Physics");
System.out.println(topics);
topics = removeElement(topics, "Math");
System.out.println(topics);
[Art, Math, Science, History, Physics]
[Art, Science, History, Physics, null]
You can do it like this.
Map<Integer, String> map = new HashMap<>(Map.of(1,"Art", 2, "Math",
3,"Science", 4,"History", 5,"Physics"));
System.out.println(map);
delete(2,map);
System.out.println(map);
public static void delete(int key, Map<Integer,String> map) {
for (int i = key; i <= map.size(); i++) {
map.put(i, map.get(i+1));
}
But there is no reason to do so. Your keys imply a linear ordering which will certainly work. But why not just use a List of values and simply delete them with the built in methods?
Then you don't need a fancy method to do so. You can just do it like this.
List<String> list = new ArrayList<>(List.of("Art", "Math", "Science", "History", "Physics"));
System.out.println(list);
list.remove("Math");
System.out.println(list);
If you really want a null value at the end you can add it. But it serves little value as far as I can tell.
private Map<Integer, String> values = new HashMap<>();
public void add(String s) {
values.put(values.size(), s);
}
public void remove(int slot) {
for (int i = slot; i <= values.size(); i++) {
if (i == slot) {
values.remove(slot);
} else {
String s = values.get(i);
values.put(i - 1, s);
values.remove(i);
}
}
values.put(values.size(), null);
}
public static void main(String[] args) {
Main4 m = new Main4();
for (int i = 0; i < 10; i++) {
m.add(String.valueOf(i));
}
System.out.println(m.values);
m.remove(3);
System.out.println(m.values);
}

Read objects content from hashmaps

I need to save pairs (string,object) into a hashmap. Basically I managed to populate the hashmap but I don't know how to access the values stored into memory.
This is my code:
HashMap<String, speedDial> SDs = new HashMap<String, speedDial>();
speedDial sd = new speedDial();
SDs.put(String.valueOf(temp),sd); whre temp is my index and sd my object
Then I fill in data into the sd reading them from an xml file.
When I debug the project with eclypse I can see the values are stored correctly into memory, but I've no idea how to retrive the string values associated to the object, see below the SD object format
class speedDial{
String label, dirN;
speedDial (String l, String dN) {
this.label = l;
this.dirN = dN;
}
}
See the picture below: it highlights the data I'm trying to access!
enter image description here
When I try to access the hashmap and print it's values I only got the last one, I use the following:
for ( int k = 0; k <50; k++) {
speedDial.printSD(SDs.get(String.valueOf(k)));
}
This is my printSD method taken from the speedDial class:
public static void printSD (speedDial SD) {
System.out.println("Dir.N: " + SD.dirN + " Label: " + SD.label);
}
And this is the output for all the 50 iterations, that is the last element I added to the hashmap in another for cycle that reads from a xml file.
Dir.N: 123450 Label: label5
Given a HashMap such as:
SpeedDial speedDial1 = new SpeedDial("test1", "test2");
SpeedDial speedDial2 = new SpeedDial("test3", "test4");
SpeedDial speedDial3 = new SpeedDial("test5", "test6");
HashMap<String, SpeedDial> exampleHashMap = new HashMap<>(3);
exampleHashMap.put("key1", speedDial1);
exampleHashMap.put("key2", speedDial2);
exampleHashMap.put("key3", speedDial3);
You can retrieve the value for a given key like so:
SpeedDial exampleOfGetValue = exampleHashMap.get("key1");
System.out.println(exampleOfGetValue.label);
System.out.println(exampleOfGetValue.dirN);
This outputs:
test1
test2
If you want to retrieve the keys for a given value then you could use something like:
public final <S, T> List<S> getKeysForValue(final HashMap<S, T> hashMap, final T value) {
return hashMap.entrySet()
.stream()
.filter(entry -> entry.getValue().equals(value))
.map(Map.Entry::getKey)
.collect(Collectors.toList());
}
If you call this function like so:
List<String> exampleOfGetKeys = getKeysForValue(exampleHashMap, speedDial1);
System.out.println(exampleOfGetKeys);
It would output a list of all keys that have this value:
[key1]
The following code will iterate through the map and will store the key and values in two lists.
List<String> keys = new ArrayList();
List<Object> values = new ArrayList();
for (Map.Entry<String, Object> speedDial: SDs.entrySet()) {
Object speedDialValue = speedDial.getValue();
String key= speedDial.getKey();
keys.add(key);
values.add(speedDialValue);
}
To retrieve the String value, typically getters are used as it is recommended to use the private modifier for your class attributes.
public class speedDial{
private String label, dirN;
public speedDial (String l, String dN) {
this.label = l;
this.dirN = dN;
}
public String getLabel(){
return this.label;
}
public String getDirN(){
return this.dirN;
}
}
The you can simply use yourObject.getLabel(); or yourObject.getDirN();
Hope that helps!
SDs.keySet() Gives you the Set of the keys of your HashMap
You can have the list of values using
for (String mapKey : SDs.keySet()) {
System.out.println("key: "+mapKey+" value: "+ SDs.get(mapKey).toString());
}
Yous have to write a toString() fonction for your speedDial

how to find the duplicates in ArrayList using hashmap in java?

my program is reading large txt files(in MBs) which contain the source ip and destination ip(for example 192.168.125.10,112.25.2.1) ,,,Here read is an ArrayList in which the data is present.
i have generated unique ids(uid int type) using srcip and destip and now i am storing in
static ArrayList<Integer[]> prev = new ArrayList<Integer[]>();
where Array is
:-
static Integer[] multi1;
multi1 = new Integer[]{(int)uid,count,flag};
i have to print the all uids with there count or their frequencies using hashmap.
Plz give some solution...
for (ArrayList<String> read : readFiles.values())
{
if(file_count<=2)
{
for(int i=0 ; i<read.size() ; i++)
{
String str1=read.get(i).split(",")[0];//get only srcIP
String str2=read.get(i).split(",")[1];//get only destIP
StringTokenizer tokenizer1=new StringTokenizer(str1,".");
StringTokenizer tokenizer2=new StringTokenizer(str2,".");
if(tokenizer1.hasMoreTokens()&&tokenizer2.hasMoreTokens())
{
sip_oct1=Integer.parseInt(tokenizer1.nextToken());
sip_oct2=Integer.parseInt(tokenizer1.nextToken());
sip_oct3=Integer.parseInt(tokenizer1.nextToken());
sip_oct4=Integer.parseInt(tokenizer1.nextToken());
dip_oct1=Integer.parseInt(tokenizer2.nextToken());
dip_oct2=Integer.parseInt(tokenizer2.nextToken());
dip_oct3=Integer.parseInt(tokenizer2.nextToken());
dip_oct4=Integer.parseInt(tokenizer2.nextToken());
uid=uniqueIdGenerator(sip_oct1,sip_oct2,sip_oct3,sip_oct4,dip_oct1,dip_oct2,dip_oct3,dip_oct4);
}
multi1 = new Integer[]{(int)uid,count,flag};
prev.add(multi1);
System.out.println(prev.get(i)[0]);//getting uids from prev
Map<ArrayList<Integer []> , Integer> map = new HashMap<ArrayList<Integer[]>, Integer>();
for (int j=0 ; j<prev.size() ; j++)
{
Integer temp=map.get(prev.get(i)[0]);
count = map.get(temp);
map.put(temp, (count == null) ? 1 : count++);
}
printMap(map);
System.out.println("uids--->"+prev.get(i)[0]+" Count--- >"+count+" flag--->"+prev.get(i)[2]);
}
}
file_count++;
}
}
public static void printMap(Map<ArrayList<Integer[]>, Integer> map)
{
for (Entry<ArrayList<Integer[]>, Integer> entry : map.entrySet())
{
System.out.println(" Value : "+ entry.getValue()+"key : "+entry.getKey());
}
}
public static double uniqueIdGenerator(int oc1,int oc2,int oc3,int oc4,int oc5,int oc6,int oc7,int oc8)
{
int a,b;
double c;
a=((oc1*10+oc2)*10+oc3)*10+oc4;
b=((oc5*10+oc6)*10+oc7)*10+oc8;
c= Math.log(a)+Math.log(b);
return Math.round(c*1000);
}
Now understanding what you want, there are (at least) 2 ways of doing this.
1st: Make a list with the uid's. Then a second list where you can have a value (your uid) and keep a count. Was thinking of HashMap, but there you can not easily change the count. Maybe an ArrayList of a list with 2 values.
Then loop over your list with the uid's, check with a second for loop if the uid is already in the second list. If it is, add one to the count. If it is not, add it to the list.
2nd: Do the same thing, but then with classes (very Java). Then you can put even more info into the class ;)
Hope this helps!
*edit: #RC. indeed gives cleaner code.

Sum value Of Class Objects Property In ArrayList

I have an ArrayList which having many objects. I want to do sum of values of the same property name.
Examples Data in Array List which is Objects of ProfitAndLossDataDO
"Michel" , 5000
"Alex" , 5000
"Edvin" , 4000
"Sosha" , 3000
"Michel" , 2000
"Alex" , 3000
And the Result Would be (Sum of values when person are same)-
"Michel" ,7000
"Alex" , 8000
"Edvin" , 4000
"Sosha" , 3000
The Logic class ProfitAndLossDataDO
public class ProfitAndLossDataDO {
String ledgerName;
double ledgerAmount;
public ProfitAndLossDataDO() {
}
public ProfitAndLossDataDO(String ledgerName, double ledgerAmount) {
this.ledgerName = ledgerName;
this.ledgerAmount = ledgerAmount;
}
public String getLedgerName() {
return ledgerName;
}
public void setLedgerName(String ledgerName) {
this.ledgerName = ledgerName;
}
public double getLedgerAmount() {
return ledgerAmount;
}
public void setLedgerAmount(double ledgerAmount) {
this.ledgerAmount = ledgerAmount;
}
#Override
public String toString()
{
return ("ledger name : "+this.getLedgerName()+" Amount : "+this.getLedgerAmount());
}
}
Thanks
I'd iterate the list and collect the results in a map:
public static List<ProfitAndLossDataDO> sumPerLedgerName
(List<ProfitAndLossDataDO> list) {
Map<String, ProfitAndLossDataDO> map = new HashMap<>();
for (ProfitAndLossDataDO p : list) {
String name = p.getLedgerName();
ProfitAndLossDataDO sum = map.get(name);
if (sum == null) {
sum = new ProfitAndLossDataDO(name, 0.0);
map.put(name, sum);
}
sum.setLedgerAmount(sum.getLedgerAmount() + p.getLedgerAmount());
}
return new ArrayList<>(map.values());
}
EDIT:
Java 8's enhancements to the Map interface allow us to implement this method in a slightly more elegant way, with the annoying if block in the middle:
public static List<ProfitAndLossDataDO> sumPerLedgerName
(List<ProfitAndLossDataDO> list) {
Map<String, ProfitAndLossDataDO> map = new HashMap<>();
for (ProfitAndLossDataDO p : list) {
String name = p.getLedgerName();
ProfitAndLossDataDO sum = map.computeIfAbsent(name, n -> new ProfitAndLossDataDO(n, 0.0));
sum.setLedgerAmount(sum.getLedgerAmount() + p.getLedgerAmount());
}
return new ArrayList<>(map.values());
}
You can use a Hash Map as aleroot suggested. Use name as the key and sum as the value. Whenever you need to insert value just check such entry exists with the same key and update it.
public class ProfitAndLossDataDO {
HashMap<String, Double> data = new HashMap<String, Double>();
public ProfitAndLossDataDO() {
}
public void updateLedger(String ledgerName, double ledgerAmount) {
double temp;
if(data.containsKey(ledgerName)) {
temp = data.get(ledgerName)+ledgerAmount;
data.put(ledgerName,temp);
}
else {
data.put(ledgerName,ledgerAmount);
}
}
}
Why you don't just put them in an Map based collection with key/value pairs ?
I think that in this case a Map based collection is more suitable, for the data you have and the context in which you want to use it.
If you need to preserve the single items inside the list, you could use a linked list as Value of the map .
For example :
HashMap<String, LinkedList<Double>> cache = new HashMap<String, LinkedList<Double>>();
and SUM each element of the value LinkedList to find the total amount ... You could even wrap the LinkedList of doubles into a container object with helper functions like getTotal() or Sum().

Create a 2d Boolean array in Java from table data

I have a .csv file of type:
Event Participant
ConferenceA John
ConferenceA Joe
ConferenceA Mary
ConferenceB John
ConferenceB Ted
ConferenceC Jessica
I would like to create a 2D boolean matrix of the following format:
Event John Joe Mary Ted Jessica
ConferenceA 1 1 1 0 0
ConferenceB 1 0 0 1 0
ConferenceC 0 0 0 0 1
I start by reading in the csv and using it to initialize an ArrayList of type:
AttendaceRecord(String title, String employee)
How can I iterate through this ArrayList to create a boolean matrix like the one above in Java?
This is the easiest way I can think of for you. This answer can certainly be improved or done in a completely different way. I'm taking this approach because you mentioned that you are not completely familiar with Map (I'm also guessing with Set). Anyway let's dive in.
In your AttendanceRecord class you are going to need the following instance variables: two LinkedHashSet and one LinkedHashMap. LinkedHashSet #1 will store all conferences and LinkedHashSet #2 will store all participants. The LinkedHashMap will store the the conferences as keys and participants list as values. The reason for this will be clear in a minute. I'll first explain why you need the LinkedHashSet.
Purpose of LinkedHashSet
Notice in your 2d array, the rows (conferences) and columns (participants) are arranged in the order they were read. Not only that, all duplicates read from the file are gone. To preserve the ordering and eliminate duplicates a LinkedHashSet fits this purpose perfectly. Then, we will have a one-to-one relationship between the row positions and the column positions of the 2d array and each LinkedHashSet via their array representation. Let's use Jhon from ConferenceA for example. Jhon will be at position 0 in the array representation of the participant Set and ConferenceA will be at position 0 in the array representation of the conference Set. Not only that, the size of each array will be used to determine the size of your 2d array (2darray[conferenceArrayLength][participantArrayLength])
Purpose of the LinkedHashMap
We need the LinkedHashMap to preserve the ordering of the elements (hence Linked). The elements will be stored internally like this.
ConferenceA :Jhon Joe Mary
ConferenceB :Jhon Ted
ConferenceC :Jessica
We will then iterate through the data structure and send each key value pair to a function which returns the position of each element from each array returned from each LinkedHashSet. As each row and column position is returned, we will add a 1 to that position in the 2d array.
Note: I used an Integer array for my example, substitute as needed.
AttendanceRecord.java
public class AttendanceRecord {
private Map<String, ArrayList> attendanceRecordMap = new LinkedHashMap<String, ArrayList>();
private Set<String> participants = new LinkedHashSet<String>();
private Set<String> conferences = new LinkedHashSet<String>();
public AttendanceRecord() {
}
public Map<String, ArrayList> getAttendanceRecordMap() {
return attendanceRecordMap;
}
public Object[] getParticipantsArray() {
return participants.toArray();
}
public Object[] getConferencesArray() {
return conferences.toArray();
}
public void addToRecord(String title, String employee) {
conferences.add(title);
participants.add(employee);
if (attendanceRecordMap.containsKey(title)) {
ArrayList<String> tempList = attendanceRecordMap.get(title);
tempList.add(employee);
} else {
ArrayList<String> attendees = new ArrayList<String>();
attendees.add(employee);
attendanceRecordMap.put(title, attendees);
}
}
}
Test.java
public class Test {
public static void main(String[] args) {
AttendanceRecord attendanceRecord = new AttendanceRecord();
//There are hardcoded. You will have to substitute with your code
//when you read the file
attendanceRecord.addToRecord("ConferenceA", "Jhon");
attendanceRecord.addToRecord("ConferenceA", "Joe");
attendanceRecord.addToRecord("ConferenceA", "Mary");
attendanceRecord.addToRecord("ConferenceB", "Jhon");
attendanceRecord.addToRecord("ConferenceB", "Ted");
attendanceRecord.addToRecord("ConferenceC", "Jessica");
int[][] jaccardArray = new int[attendanceRecord.getConferencesArray().length][attendanceRecord.getParticipantsArray().length];
setUp2dArray(jaccardArray, attendanceRecord);
print2dArray(jaccardArray);
}
public static void setUp2dArray(int[][] jaccardArray, AttendanceRecord record) {
Map<String, ArrayList> recordMap = record.getAttendanceRecordMap();
for (String key : recordMap.keySet()) {
ArrayList<String> attendees = recordMap.get(key);
for (String attendee : attendees) {
int row = findConferencePosition(key, record.getConferencesArray());
int column = findParticipantPosition(attendee, record.getParticipantsArray());
System.out.println("Row inside " + row + "Col inside " + column);
jaccardArray[row][column] = 1;
}
}
}
public static void print2dArray(int[][] jaccardArray) {
for (int i = 0; i < jaccardArray.length; i++) {
for (int j = 0; j < jaccardArray[i].length; j++) {
System.out.print(jaccardArray[i][j]);
}
System.out.println();
}
}
public static int findParticipantPosition(String employee, Object[] participantArray) {
int position = -1;
for (int i = 0; i < participantArray.length; i++) {
if (employee.equals(participantArray[i].toString())) {
position = i;
break;
}
}
return position;
}
public static int findConferencePosition(String employee, Object[] conferenceArray) {
int position = -1;
for (int i = 0; i < conferenceArray.length; i++) {
if (employee.equals(conferenceArray[i])) {
position = i;
break;
}
}
return position;
}
}
Basically you'll want to start by searching through your input strings to find each of the names (String.contains) and set a boolean array of each field name.
Then you'll make an array of those boolean arrays (or a list, whatever).
Then you simply sort through them, looking for T/F and printing corresponding messages.
I included some very rough pseudocode, assuming I am understanding your problem correctly.
// For first row
List labelStrings[];
labelStrings = {"Event", "John", "Joe", "Mary", "Ted", "Jessica"};
// For the matrix data
// List to iterate horizontally EDIT: Made boolean!
List<Boolean> strList= new ArrayList()<List>;
// List to iterate vertically
List<List> = listList new ArrayList()<List>;
/* for all the entries in AttendanceRecord (watch your spelling, OP)
for all data sets mapping title to employee
add the row data to strList[entry_num] */
for (int i = 0; i < listList.size()-1; i++)
for (int j = 0; j < labelStrings.size()-1; j++)
{
if (i == 0)
System.out.println(strList[j] + "\t\n\n");
else
{
// print listLists[i][j]
}
// iterate row by row (for each horizontal entry in the column of entries)
}
Sorry, I'm just reading through the comments now.
You'll definitely want to arrange your data in a way that is easy to iterate through. Since you have a fixed table size, you could hardcode a boolean array for each entry and then print on validation they were mapped to the event as indicated in your input string.
Try creating a hash map containing
HashMap map = new HashMap<conferenceStr, HashMap<nameStr, int>>()
As you iterate through your ArrayList, you can do something like
innerMap = map.get(conferenceStr)
innerMap.put(nameStr, 1)
of course you'll need some initialization logic, like you can check if innerMap.get(nameStr) exists, if not, iterate over every inner map and innerMap.put(nameStr, 0)
This structure can be used to generate that final 2D boolean matrix.
Elaboration edit:
ArrayList<AttendanceRecord> attendanceList = new ArrayList<AttendanceRecord>();
// populate list with info from the csv (you implied you can do this)
HashMap<String, HashMap<String, Integer>> map = new HashMap<String, HashMap<String, Integer>>();
//map to store every participant, this seems inefficient though
HashMap<String, Integer>> participantMap = new HashMap<String, Integer>();
for (AttendanceRecord record : attendanceList) {
String title = record.getTitle();
String employee = record.getEmployee();
participantMap.put(employee, 0);
HashMap<String, Integer> innerMap = map.get(title);
if (innerMap == null) {
innerMap = new HashMap<String, Integer>();
}
innerMap.put(employee, 1);
}
//now we have all the data we need, it's just about how you want to format it
for example if you wanted to just print out a table like that you could iterate through every element of map doing this:
for (HashMap<String, Integer> innerMap : map.values()) {
for (String employee : participantMap.values()) {
if (innerMap.get(employee)) {
//print 1
}
else
//print 0
}
}

Categories