Can any one explain this strange behavior of java HashMap? - java

I have used HashMap in Java a lot but has never encountered this behavior. I have to types, Item and ItemGroup. They are defined as shown in the following codes snippets.
public class Item {
String id;
float total;
}
public class ItemGroup {
String keyword;
int frequency;
List<Item> items;
}
So ItemGroup consists of 0..* items. These items have a keyword in common and the keyword appears in the system with some frequency. Now the fun part, I have following method that given a list of items creates a list of groups.
public static ItemGroup[] createGroups(Item[] items){
HashMap<String, ItemGroup> groups = new HashMap<String, ItemGroup>();
String[] words;
for (int i=0; i<items.length; i++){
words = items[i].getId().split(REGEX);
// Process keywords
for (int j=0; j<words.length; j++){
if (words[j].isEmpty()) break;
ItemGroup group = groups.get(words[j]);
if (group != null){
group.incrementFrequency();
group.getItems().add(items[i]);
}else {
group = EconomFactory.eINSTANCE.createItemGroup();
group.setKeyword(words[j]);
group.incrementFrequency();
group.getItems().add(items[i]);
groups.put(words[j], group);
}
}
}
return groups.values().toArray(new ItemGroup[0]);
}
The part where it gets strange is when adding the item to an itemgroup (the line group.getItems().add(items[i]);). During rehashing the group loses its items in a strange way. Using Debugging I can see that the group contains the item just after the operation but latter on, e.g. when returning the value of the method, all the groups has lost their items.
I tried this:
public static ItemGroup[] createGroups(Item[] items){
HashMap<String, ItemGroup> groups = new HashMap<String, ItemGroup>();
String[] words;
for (int i=0; i<items.length; i++){
words = items[i].getId().split(REGEX);
// Create a new item based on the current one in the list
Item item = EconomFactory.eINSTANCE.createItem();
item.setId(items[i].getId());
item.setTotal(items[i].getTotal());
// Process key words
for (int j=0; j<words.length; j++){
if (words[j].isEmpty()) break;
ItemGroup group = groups.get(words[j]);
if (group != null){
group.incrementFrequency();
group.getItems().add(item);
}else {
group = EconomFactory.eINSTANCE.createItemGroup();
group.setKeyword(words[j]);
group.incrementFrequency();
group.getItems().add(item);
groups.put(words[j], group);
}
}
}
return groups.values().toArray(new ItemGroup[0]);
}
but got the same result. The following solution, however, works just fine.
public static ItemGroup[] createGroups(Item[] items){
HashMap<String, ItemGroup> groups = new HashMap<String, ItemGroup>();
String[] words;
for (int i=0; i<items.length; i++){
words = items[i].getId().split(REGEX);
// Process key words
for (int j=0; j<words.length; j++){
if (words[j].isEmpty()) break;
// Create a new item based on the current one in the list
Item item = EconomFactory.eINSTANCE.createItem();
item.setId(items[i].getId());
item.setTotal(items[i].getTotal());
ItemGroup group = groups.get(words[j]);
if (group != null){
group.incrementFrequency();
group.getItems().add(item);
}else {
group = EconomFactory.eINSTANCE.createItemGroup();
group.setKeyword(words[j]);
group.incrementFrequency();
group.getItems().add(item);
groups.put(words[j], group);
}
}
}
return groups.values().toArray(new ItemGroup[0]);
}
The method EconomFactory.eINSTANCE.createItemGroup() is implemented as follow:
public ItemGroup createItemGroup() {
ItemGroupImpl itemGroup = new ItemGroupImpl();
return itemGroup;
}
where ItemGroupImpl is the implementation of ItemGroup, e.i. it subclasses the ItemGroup. It is because I use EMF (Eclipse Modeling Framework).
Can anyone please explain this behavior (why the ItemGroup objects lose their items)?
Here is the codes for ItemGroup and ItemGroupImpl. The same way looks the codes for Item and ItemImpl.
public interface ItemGroup extends EObject {
String getKeyword();
void setKeyword(String value);
int getFrequency();
void setFrequency(int value);
EList<Item> getItems();
void incrementFrequency();
}
public class ItemGroupImpl extends EObjectImpl implements ItemGroup {
protected static final String KEYWORD_EDEFAULT = null;
protected String keyword = KEYWORD_EDEFAULT;
protected static final int FREQUENCY_EDEFAULT = 0;
protected int frequency = FREQUENCY_EDEFAULT;
protected EList<Item> items;
protected ItemGroupImpl() {
super();
}
#Override
protected EClass eStaticClass() {
return EconomPackage.Literals.ITEM_GROUP;
}
public String getKeyword() {
return keyword;
}
public void setKeyword(String newKeyword) {
String oldKeyword = keyword;
keyword = newKeyword;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET,
EconomPackage.ITEM_GROUP__KEYWORD, oldKeyword, keyword));
}
public int getFrequency() {
return frequency;
}
public void setFrequency(int newFrequency) {
int oldFrequency = frequency;
frequency = newFrequency;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET,
EconomPackage.ITEM_GROUP__FREQUENCY, oldFrequency, frequency));
}
public EList<Item> getItems() {
if (items == null) {
items = new EObjectContainmentEList<Item>(Item.class, this,
EconomPackage.ITEM_GROUP__ITEMS);
}
return items;
}
public void incrementFrequency() {
this.frequency = getFrequency() + 1;
}
#Override
public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID,
NotificationChain msgs) {
switch (featureID) {
case EconomPackage.ITEM_GROUP__ITEMS:
return ((InternalEList<?>)getItems()).basicRemove(otherEnd,
msgs);
}
return super.eInverseRemove(otherEnd, featureID, msgs);
}
#Override
public Object eGet(int featureID, boolean resolve, boolean coreType) {
switch (featureID) {
case EconomPackage.ITEM_GROUP__KEYWORD:
return getKeyword();
case EconomPackage.ITEM_GROUP__FREQUENCY:
return getFrequency();
case EconomPackage.ITEM_GROUP__ITEMS:
return getItems();
}
return super.eGet(featureID, resolve, coreType);
}
#SuppressWarnings("unchecked")
#Override
public void eSet(int featureID, Object newValue) {
switch (featureID) {
case EconomPackage.ITEM_GROUP__KEYWORD:
setKeyword((String)newValue);
return;
case EconomPackage.ITEM_GROUP__FREQUENCY:
setFrequency((Integer)newValue);
return;
case EconomPackage.ITEM_GROUP__ITEMS:
getItems().clear();
getItems().addAll((Collection<? extends Item>)newValue);
return;
}
super.eSet(featureID, newValue);
}
#Override
public void eUnset(int featureID) {
switch (featureID) {
case EconomPackage.ITEM_GROUP__KEYWORD:
setKeyword(KEYWORD_EDEFAULT);
return;
case EconomPackage.ITEM_GROUP__FREQUENCY:
setFrequency(FREQUENCY_EDEFAULT);
return;
case EconomPackage.ITEM_GROUP__ITEMS:
getItems().clear();
return;
}
super.eUnset(featureID);
}
#Override
public boolean eIsSet(int featureID) {
switch (featureID) {
case EconomPackage.ITEM_GROUP__KEYWORD:
return KEYWORD_EDEFAULT == null ? keyword != null :
!KEYWORD_EDEFAULT.equals(keyword);
case EconomPackage.ITEM_GROUP__FREQUENCY:
return frequency != FREQUENCY_EDEFAULT;
case EconomPackage.ITEM_GROUP__ITEMS:
return items != null && !items.isEmpty();
}
return super.eIsSet(featureID);
}
#Override
public String toString() {
if (eIsProxy()) return super.toString();
StringBuffer result = new StringBuffer();
result.append("(keyword: ");
result.append(keyword);
result.append(", frequency: ");
result.append(frequency);
result.append(')');
return result.toString();
}
}

In your second set of Code, where is I intialized?
public static ItemGroup[] createGroups(Item[] items){
HashMap<String, ItemGroup> groups = new HashMap<String, ItemGroup>();
String[] words;
// Create a new item based on the current one in the list
Item item = EconomFactory.eINSTANCE.createItem();
item.setId(items[i].getId());
item.setTotal(items[i].getTotal());
The variable i has not been initialized in this context, so it could be any value (since its not blowing up, I assume you have a global "i" somehwere else in your code, and you are starting your method with that value instaed of 0.
In your code that is working you have i initialized in the method before you access it :
public static ItemGroup[] createGroups(Item[] items){
HashMap<String, ItemGroup> groups = new HashMap<String, ItemGroup>();
String[] words;
for (int i=0; i<items.length; i++){
words = items[i].getId().split(REGEX);
// Process key words
for (int j=0; j<words.length; j++){
if (words[j].isEmpty()) break;
So, that is my guess as to why you are seeing the behavior you are seeing... ALWAYS INITIALIZE VARIABLES BEFORE ACCESSING THEM.

Tell us please what happens in EconomFactory.eINSTANCE.createItemGroup() ? I cannot tell if a unique instance with a unique items List is created each time.
I tried it out with some modifications (I am not currently using Java 6 so can't use String.isEmpty) and assuming regular object creation and it works for me. See below my runnable example (something like which you should post next time you ask a question):
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ItemGrouper {
public static class Item {
String id;
float total;
Item(String id) {
this.id = id;
}
public String getId() {
return id;
}
}
public static class ItemGroup {
String keyword;
int frequency;
List<Item> items = new ArrayList<ItemGrouper.Item>();
public void incrementFrequency() {
frequency++;
}
public List<Item> getItems() {
return items;
}
public void setKeyword(String string) {
keyword = string;
}
#Override
public String toString() {
return String.format("key=%s freq=%s", keyword, frequency);
}
}
public static ItemGroup[] createGroups(Item[] items) {
Map<String, ItemGroup> groups = new HashMap<String, ItemGroup>();
String[] words;
for (int i = 0; i < items.length; i++) {
words = items[i].getId().split(" ");
// Process keywords
for (int j = 0; j < words.length; j++) {
if (words[j].length() == 0) {
break;
}
ItemGroup group = groups.get(words[j]);
if (group == null) {
group = new ItemGroup();
group.setKeyword(words[j]);
groups.put(words[j], group);
}
group.incrementFrequency();
group.getItems().add(items[i]);
}
}
return groups.values().toArray(new ItemGroup[0]);
}
public static void main(String[] args) {
Item[] items = new Item[] {new Item("one two"), new Item("two three")};
ItemGroup[] itemgroups = createGroups(items);
System.out.println(Arrays.toString(itemgroups));
}
}
Output:
[key=one freq=1, key=two freq=2, key=three freq=1]

Related

Unit Testing Android function

I want to unit test a function within my code, but when I try to input a ArrayList into it it gives me array initializer not allowed here
here is my code:
public class CreateActivityTest {
ArrayList<String> items;
public String Add(String item, ArrayList<String> items) {
if (items.contains(item.toLowerCase().trim())) {
return null;
}
else if (item == null || item.trim().equals("")) {
return null;
} else {
return item.toLowerCase().replaceAll("\\s+", "");
}
}
#Test
public void addTest () throws Exception {
items = {"strawberry", "raspberry"};
String input = Add("Strawberry ", items);
String expected = null;
assertEquals(input, expected);
}
}
items = Arrays.asList("strawberry", "raspberry");
Or, if you want exactly arraylist, just
items = new ArrayList<>();
items.add("strawberry");
items.add("raspberry");

Creating Objects of a Class in Java that declares an array of object, but only one of them will print

The goal of my program is to store data for students(First Name, Last Name, ID#).I'm trying to create 4 Arrays. One array will hold the combined value of each student object that I'm adding(myDB). The other 3 hold indexes to the original spot of each value(Fname,Lname,ID) and add them to an ordered array without sorting the array. The trouble I'm having is that once I add something to the Index Arrays and go to print them, it prints all of the IDs regardless of what object I call.
//class containing methods to list, add, and delete
//Class that declares the main database array that holds all three (ID,First,Last)
import java.io.FileInputStream;
import java.util.*;
public class DataBase
{
private String tempID, tempFname, tempLname;
private DataBaseArray myDB;
private int nextDBRecord;
private IndexArray ID;
private IndexArray First;
private IndexArray Last;
public DataBase()
{
nextDBRecord = 0;
myDB =new DataBaseArray(100);
ID=(new IndexArray(100));
First=new IndexArray(100);
Last=new IndexArray(100);
}
void addData(String last, String first, String id)
{
tempLname = new String(last);
tempFname = new String(first);
tempID = new String(id);
//ID.insert(new IndexRecord(tempID, nextDBRecord));
First.insert(new IndexRecord(tempFname,nextDBRecord));
Last.insert(new IndexRecord(tempLname,nextDBRecord));
//Adds to main DB with
myDB.getStudentArray()[nextDBRecord]= (new DataBaseRecord(tempLname,tempFname,tempID));
System.out.println(myDB.getStudentArray()[nextDBRecord]);
nextDBRecord++;
}
void addIt ()
{
Scanner keyb = new Scanner(System.in);
System.out.println("Please enter the ID for new student entry");
tempID=keyb.next();
ID.insert(new IndexRecord(tempID, nextDBRecord));
System.out.println("Please enter the first name of the new student");
tempFname=keyb.next();
First.insert(new IndexRecord(tempFname, nextDBRecord));
System.out.println("Please eneter the last name of the new student");
tempLname=keyb.next();
Last.insert(new IndexRecord(tempLname,nextDBRecord));
//Adds to main DB with
myDB.getStudentArray()[nextDBRecord]= (new DataBaseRecord(tempLname,tempFname,tempID));;
nextDBRecord++;
}
void findIt()
{
}
void list (int type, int order)
{
First.printIt(order);
}
}
//Class that creates the objects to add to Iarray Farray Iarray
//IndexArray is a static array
//Creates a single entry into the IndexArray
//Need a compareTo method that gives the where value of each object
public class IndexRecord
{
private String key; //Value
private int where; //Where it is at in DataBaseArray
IndexRecord (String value, int position)
{
setKey(new String(value));
where = position;
}
public String toString()
{
return getKey()+" "+ String.valueOf(where);
}
public String getKey() //Getter for key value of the new student that is being added
{
return key;
}
public void setKey(String key) //Setter for key value of the new student that is being added
{
this.key = key;
}
}
//Same as OrderedArray Class
//Add Iterator methods. Instead of printing here, tell DataBase class what DatabaseRecord objects to print
public class IndexArray
{
private static IndexRecord[] irArray;
private int nOfElem; //Should be the same for each array so only 1 counter is needed
private int maxSize;
private int theIterator;
public IndexArray(int size)
{
nOfElem = 0;
maxSize=size;
irArray = new IndexRecord[size];
}
//-----------------------------Getters and Setters-------------------------------------
public int size() //Getter to find num of elements in array that can be called in other class
{ return nOfElem; }
public IndexRecord[] getIRarray()
{
return irArray;
}
//---------------------Iterator Methods-----------------------------------------------------
void iteratorToFront()
{
theIterator=(nOfElem>0? 0 : -1);
}
void iteratorToBack()
{
theIterator=(nOfElem>0 ? nOfElem-1 : -1);
}
boolean hasNext()
{
return (theIterator==nOfElem-1? false:true );
}
boolean hasPrevious()
{
return (theIterator==0? false : true);
}
public IndexRecord getIterator()
{
return(theIterator==-1 ? null :irArray[theIterator]);
}
int getNext()
{
theIterator=(hasNext()? theIterator+1: -1);
return(theIterator==-1? null : theIterator);
}
int getPrevious()
{
theIterator=(hasPrevious()? theIterator-1:-1);
return (theIterator==-1? null : theIterator);
}
//------------------Methods Called In Main---------------------------------------
public boolean insert(IndexRecord ir)
{
if(maxSize==nOfElem) return false;
int j;
for(j=nOfElem-1;j>=0;j--)
{
if(irArray[j].getKey().compareToIgnoreCase(ir.getKey())<0)break;
{
irArray[j+1]=irArray[j]; //Pushes all objects down to make room for new one
}
}
irArray[j+1]=ir;
nOfElem++;
return true;
}
public int find(String searchKey)
{
int lowerBound = 0;
int upperBound = nOfElem-1;
int currentRef;
while(true)
{
currentRef = (lowerBound + upperBound) / 2;
String tempValue = String.valueOf(irArray[currentRef].getKey());
if(tempValue.compareTo(searchKey) == 0)
return currentRef;
else if (lowerBound > upperBound)
return nOfElem; //returns a pointer to an empty slot
else
{
if(tempValue.compareTo(searchKey) > 0)
lowerBound = currentRef++;
else
upperBound = currentRef - 1;
}
}
}
//delete
public void printIt(int order)
{
switch(order)
{
case -1:
iteratorToBack();
break;
case 1:
iteratorToFront();
while(hasNext())
{
System.out.println(irArray[getNext()]);
}
break;
default:
}
}
}

how to add object in Arraylist which contains matched items only java

I have two Arraylist one List that is ShoppingList which contains item such as [tea,milk,sugar]
and another List which is my Recipe object ingredients list...So how to add object only in a result list which contains these items ?
The problem is that its add multiple object with contains these items
My code which finds common items in both list :
final List<RecipeN> result = new ArrayList<RecipeN>();
for (RecipeN rn : allrec) {
for (ShoppingList sl : allitems) {
for(int i = 0;i<rn.getIngredient().size();i++) {
if (rn.getIngredients(i).contains(sl.getrName())) {
result.add(rn);
}
}
}
public class RecipeN {
private String recName;
private List<String> ingredient = new ArrayList<String>();
public RecipeN(){
}
public RecipeN(String item){
this.ingredient.add(item);
}
public List<String> getIngredient(){
return ingredient;
}
public String getIngredients(int i){
return ingredient.get(i);
}
public void setIngredient(List<String> item){
this.ingredient = item;
}
public String getRecName() {
return recName;
}
public void setRecName(String recName) {
this.recName = recName;
}
#Override
public String toString() {
return recName;
}
}
Use method retainAll(Collection c) to only keep the items in a shopping list that appears in a recipe. Code example is as below:
List<Item> recipe = new ArrayList<>();
List<Item> shoppingList = new ArrayList<>();
... your code ...
shoppingList.retainAll(recipe);
If you want to have only 1 times each match recipe you should use a HashSet in order to not have duplicate in the list.
final Set<RecipeN> result = new HashSet<RecipeN>();
for (RecipeN rn : allrec) {
for (ShoppingList sl : allitems) {
for(int i = 0;i<rn.getIngredient().size();i++) {
if (rn.getIngredients(i).contains(sl.getrName())) {
result.add(rn);
}
}
}
}
if you want to keep an ArrayList you can do that :
final Set<RecipeN> result = new HashSet<RecipeN>();
for (RecipeN rn : allrec) {
boolean recipeMatched = false;
for (ShoppingList sl : allitems) {
for(int i = 0;i<rn.getIngredient().size();i++) {
if (rn.getIngredients(i).contains(sl.getrName())) {
recipeMatched = true;
result.add(rn);
break;
}
if (recipeMatched)
break;
}
if (recipeMatched)
break;
}
}

Java ArrayList.contains() & add() method

So I'm having this problem with adding an element to an ArrayList
I have a class Media with 3 fields and another class Mediatheque with 1 field(which is an ArrayList).
Let's say I have:
A Mediatheque media = new Mediatheque
An equals(Media m) method in class Media < (important method)
I need to write a method add(Media m) which:
If the media.contenu does contain an element equals to the Media m I want to add, I must NOT add it and increase the nbEx field of the element contained in media.contenu
-Else I can add it using the add method provided by the ArrayList ( This doesn't seem too hard)
So I tried to write a contains(Media) method which uses the equals(Media m) method I wrote for the Media class and then use the contains method in the add method.
My question is that how am I supposed to write the add method? < (The Question)
I must write this using ArrayList, it is a school assignment
Sorry about the long code and the bad English, I'm a complete noob.
Here is my Media class:
package Ex1;
public class Media {
private final String support; // Format: Book, CD, DVD,etc...
private final String titre; // Title
private int nbEx; // Number of copy
public Media(String titre, String support){
this.titre = titre;
this.support = support;
this.nbEx = 1;
}
public Media (){
titre = "";
support = "";
nbEx = 0;
}
public boolean equals(Media m){
boolean equality = false;
if (m instanceof Media){
equality = (this.titre.equals(m.titre) && this.support.equals(m.support));
}
return equality;
}
public Media(Media m){
this.titre = m.titre;
this.support = m.support;
}
}
And here is my Mediatheque class:
import java.util.ArrayList;
import static java.lang.System.out;
public class Mediatheque {
ArrayList<Media> contenu;
public Mediatheque(){
this.contenu = new ArrayList<Media>();
}
public Mediatheque(Mediatheque m){
this.contenu = m.contenu;
}
public boolean contains(Media m){
int i = 0;
boolean contain = this.contenu.get(i).equals(m);
for(i = 0; i<this.contenu.size(); i++){
if(contain)
break;
}
return contain;
}
public int indexOf(Media m){
boolean retVal = this.contenu.get(i).equals(m);
for(Media i : contenu){
if(contain)
break;
}
return i;
}
public void add(Media m){
if(this.contains(m)){
this.contenu.get(this.contenu.indexOf(m)).setNbEx(this.contenu.get(this.contenu.indexOf(m)).getNbEx()+m.getNbEx());
}else{
this.contenu.add(m);
}
}
My question is that how am I supposed to write the add method?
Sorry about the long code and the bad English, I'm a complete noob.
Thank you!
As stated by #NeplatnyUdaj in the comment of your question, the use of a Map would greatly improve your code. Instead of recording the number of medias inside the Media object, use a HashMap<Media, Integer> to store your data in this way:
new HashMap<Media, Integer> map = new HashMap<Media,Integer>();
if ( map.containsKey(key) ) {
map.put(key, (map.get(key) + 1));
} else {
map.put(key, 1);
}
Where key is the media. (m in your code)
When one overrides the equals() method, one is also supposed to override the hashCode() method. The equals() method takes an Object parameter. Here's how your Media class should look like:
// Media.java
public class Media
{
private final String support;
private final String title;
public Media(String title, String support)
{
this.title = title;
this.support = support;
}
public Media(Media media)
{
this(media.title, media.support);
}
#Override
public int hashCode()
{
return 31 * title.hashCode() + support.hashCode();
}
#Override
public boolean equals(Object object)
{
if (object instanceof Media)
{
Media media = (Media) object;
return media.title.equals(title) &&
media.support.equals(support);
}
return false;
}
}
Then use a HashMap to map the media with its number of copies. Here's how that's done:
// MediaMap.java
import java.util.HashMap;
import java.util.Map;
public class MediaMap
{
// Media to its Number of Copies mapping.
private Map<Media, Integer> mediaMap;
public MediaMap()
{
mediaMap = new HashMap<>();
}
public void add(Media media)
{
mediaMap.put(media, mediaMap.getOrDefault(media, 0) + 1);
}
public void removeOneMedia(Media media)
{
if (mediaMap.containsKey(media))
{
mediaMap.put(media, mediaMap.get(media) - 1);
}
}
// And so on...
}
Without overriding the hashCode() method in the Media class, the hash based collections won't work as expected.
You can also have a look at MultiSet data structure, and use that instead.
If you are to use ArrayList then here's how its done:
// Media.java
public class Media
{
private final String support;
private final String title;
private int numberOfCopies;
public Media(Media media)
{
this(media.title, media.support, media.numberOfCopies);
}
public Media(String title, String support, int numberOfCopies)
{
this.title = title;
this.support = support;
this.numberOfCopies = numberOfCopies;
}
#Override
public int hashCode()
{
return 31 * title.hashCode() + support.hashCode();
}
#Override
public boolean equals(Object object)
{
if (object instanceof Media)
{
Media media = (Media) object;
return media.title.equals(title) &&
media.support.equals(support);
}
return false;
}
public int getNumberOfCopies()
{
return numberOfCopies;
}
public void setNumberOfCopies(int numberOfCopies)
{
this.numberOfCopies = numberOfCopies;
}
}
And here's a MediaList class which uses ArrayList:
// MediaList.java
import java.util.ArrayList;
public class MediaList
{
private ArrayList<Media> mediaList;
public MediaList()
{
mediaList = new ArrayList<>();
}
public void add(Media media)
{
set(media, +1);
}
public void remove(Media media)
{
set(media, -1);
}
private void set(Media media, int change)
{
if (change == 0)
{
return;
}
int indexOfMedia = mediaList.indexOf(media);
if (indexOfMedia != -1)
{
Media m = mediaList.get(indexOfMedia);
m.setNumberOfCopies(m.getNumberOfCopies() + change);
if (change < 0 && m.getNumberOfCopies() <= 0)
{
mediaList.remove(media);
}
}
else if (change > 0)
{
mediaList.add(media);
}
}
// And so on...
}
I have refactored your classes a little bit. I also implemented an add method. I assumed that you want to add media to the mediatheque if it is not already in the list. If it is in the list you want to add the nbex to the nbex that the item in the list has, right?
As the others I would advise you to use a HashMap() for counting if you don't need the number for your media objects.
Media.class
public class Media {
private final String support; // Format: Book, CD, DVD,etc...
private final String titre; // Title
private int nbEx; // Number of copy
public Media(String titre, String support){
this.titre = titre;
this.support = support;
this.nbEx = 1;
}
public Media(Media m){
this(m.titre, m.support);
}
public Media (){
this("", "");
nbEx = 0;
}
public boolean equals(Media m){
if (m instanceof Media){
return (this.titre.equals(m.titre) && this.support.equals(m.support));
}
return false;
}
}
Mediatheque.class
public class Mediatheque {
ArrayList<Media> contenu;
public Mediatheque(){
this.contenu = new ArrayList<Media>();
}
public Mediatheque(Mediatheque m){
this.contenu = m.contenu;
}
public boolean contains(Media m){
for(Media media: this.contenu) {
if(media.equals(m) {
return true;
}
}
return false;
}
public int indexOf(Media m){
if(this.contenu.contains(m) {
return this.contenu.indexOf(m);
}
return -1;
}
public void add(Media m){
if(this.contains(m)) {
Media media = this.contenu.get(this.contenu.indexOf(m));
media.setNbex(media.getNbex() + m.getNbex());
} else {
this.contenu.add(m);
}
}
}
Hope this helps.

Find similar integers inside of an ArrayList with Class Method

I need to iterate through and ArrayList of objects and look for a variable that has the same value for multiple objects. As the example below, I am looking through an ArrayList, that has a sub-class . All I want to do is find out if a house or condo share the same listing number for this example code. I tried using a double loop, and an enhanced loop with a method (sameListingNum) and am having trouble working it out.
Thank you
// main client class
public static void main(String[] args)
{
ArrayList<House> listings = new ArrayList();
listings.add(new House(0001, 200000.00));
listings.add(new House(0201, 200000.00));
listings.add(new House(0001, 200000.00));
listings.add(new House(0401, 200000.00));
listings.add(new House(0031, 200000.00));
listings.add(new Condo(0401, 200000.00, 4));
listings.add(new Condo(0001, 120000.00, 3));
listings.add(new Condo(0301, 220000.00, 2));
listings.add(new Condo(0001, 130000.00, 3));
listings.add(new Condo(0201, 130000.00, 3));
for(House currentHouse: listings)
System.out.println(currentHouse);
for(int i=0; i<listings.size()-1; i++)
{
for(int j=i+1; j<listings.size(); j++)
{
}
}
// House Class
public class House
{
public int listingNum;
public double price;
public House()
{
listingNum = 0;
price = 0.00;
}
public House(int newListingNum, double newPrice)
{
listingNum = newListingNum;
price = newPrice;
}
public int getListingNum()
{
return listingNum;
}
public double getPrice()
{
return listingNum;
}
public String toString()
{
return ("Listing number: "+listingNum+", Price: "+price);
}
public boolean sameListingNum(Object other)
{
if(!(other instanceof House))
return false;
else {
House objHouse = (House)other;
if(listingNum - objHouse.getListingNum() == 0)
{
System.out.println("Same listing numbers: "
+listingNum+", "+objHouse.getListingNum());
return true;
}
else
return false;
}
}
}
// Condo Class
public class Condo extends House
{
public int connectedUnits;
public Condo()
{
super();
connectedUnits = 0;
}
public Condo(int newListingNum, double newPrice, int newConUnits)
{
super(newListingNum, newPrice);
connectedUnits = newConUnits;
}
public double getPrice()
{
return price;
}
public int getListingNum()
{
return listingNum;
}
public int getConnectedUnits()
{
return connectedUnits;
}
public String toString()
{
return super.toString()+", Number of connected unints: "+connectedUnits;
}
public boolean sameListingNum(Object other)
{
if(!(other instanceof House))
return false;
else {
House objHouse = (House)other;
if(listingNum - objHouse.getListingNum() == 0)
{
System.out.println("Same listing numbers: "
+listingNum+", "+objHouse.getListingNum());
return true;
}
else
return false;
}
}
You can group it using a Map of List, like Map> groups.
Then you loop over you list and for each house/condo you put it in the group of the same listing number. At the end you will have a map where for each entry there are all houses/condos with same listing number.
Here a sample:
Map<Integer, List<House>> groups = new HashMap<Integer, List<House>>();
for (House house:listings) {
List<House> group = groups.get(house.getListingNum());
if (group == null) {
group = new ArrayList<House>();
groups.put(house.getListingNum(), group);
}
group.add(house);
}
for (Entry<Integer, List<House>> entry:groups.entrySet()) System.out.println("Listing Number "+entry.getKey()+" Houses/condos: "+entry.getValue());
Both of the other 2 answers will work alternativly you can implement comparable on the House... eg.
public class House implements Comparable<House>
#Override
public int compareTo(final House o) {
return listingNum - o.listingNum;
}
then inside your main method. Sort the Collection and check to see if the previous row has the same Id all the time.
Collections.sort(listings);
int previousListing = Integer.MIN_VALUE;
for (House currentHouse : listings) {
if (currentHouse.getListingNum() == previousListing){
System.out.println("Duplicate for " + currentHouse.getListingNum());
}
previousListing = currentHouse.getListingNum();
}
take your pick.
Try this:
foreach(House h in listings)
{
if(listings.Exists(p => p.sameListingNum(h)))
{
//do something
}
}

Categories