I'm new to java so im having some "annoying" problems. I have a class Employee which contains an int idNumber and a int phone number. Then I have a LinkedList<Employee> sorted by idNumber. I want to change the phonenumber of a certain idnumber.
I've been working with Iterators but i don't know if i'm doing it right, which I doubt.
public void setNewPhoneNumber(int idnumber, int newphone){
Iterator<IndexC> it = listEmployee.iterator();
IndexC employeeTemp = null;
boolean found = false;
while(it.hasNext() && !found){
employeeTemp = it.next();
if(employee.getIdNumber()== idnumber){
employeeTemp.setNewPhoneNumber(newphone);
found = true;
}
}
}
Yeah, I know employee.setNewPhoneNumber is wrong, but I don't know which the correct way change the value on the linkedlist. (Sorry for the bad english, not a native speaker)
Iterators are a pain; the foreach construct is a lot nicer:
public void setNewPhoneNumber(int idnumber, int newphone) {
for (Employee employee : listEmployee)
if (employee.getIdNumber() == idnumber) {
employee.setNewPhoneNumber(newphone);
return;
}
}
I'm not clear on what IndexC is, and I don't often use LinkedList - there could be some subtlety here I'm missing - but I think you're better off avoiding the iterators.
You're not "changing parameters in a Linked List", you're trying to find an object in a list and change a property of that object
You should be using a Map (such as a
HashMap) instead of a List, then you
won't have to iterate.
If you iterate, use the for loop: for(IndexC employeeTemp: employeeTemp){}
Changing the phone numer would conventionally be done through a setPhoneNubmer() method, but it depends entirely on the IndexC class whether it has such a method. Look at that class's definition.
When asking a question, always include error messages! "It doesn't work" is a really useless piece of information.
my bad, IndexC is the Employee class, "bad copy past" sorry. I don't like LinkedList but i have to use it with +5000 entries (School Exercise). I don't think using for's with so many entries is recommended.
The class as set's, get's, clones..
class Manager{
private LinkedList<Employee> listE = new LinkedList<Emploee>;
public void setNewPhoneNumber(int idnumber, int newphone)
}
One reason for it not to work is that there´s no IndexC in the list that satisfies (employee.getIdNumber()== idnumber).
Maybe you should post some extra code, for example, where is that list created, have you filled it with anything?
Besides, what is it that doesn´t work? The setting of the new phone number, or retrieving the element from the list?
In both cases, i think that you should post both methods, that is
getIdNumber();
As Mike B. says, maybe using a Map implementation would be better. Since you are considering order, maybe a SortedMap (such as TreeMap) implementation could be better.
In any case, rember you have to override two methods in your IndexC (when using maps). Otherwise, things will get messy.
equals
hashCode
http://java.sun.com/j2se/1.4.2/docs/api/java/util/LinkedList.html
You want to use a for loop with an int incrementing till you find the object you want. Then you want to use listEmployee.get() to get the object you want and edit it.
However, if you need random access to items like that, then you should not be using Linkedlists. Stick it in an ArrayList instead. That has much better random access time.
As a side note, you don't even need the for loop if the id numbers are in order from 0-whatever. You can simply listEmployee.get(idNumber)
Related
How do I compare each element in two different sets of data, and then merge certain elements of them into a new set of data?
Some info about my methods below. Note:
Not using java.lang.Collections
In one class I have these calls initializers:
BookCollection collection1 = new BookCollection(100);
BookCollection collection2 = new BookCollection(50);
BookCollection collection3 = new BookCollection(150);
And this call to my method merge(which I am trying to complete)
collection3.merge(collection1, collection2);
Anndd in another class my method merge is trying to compare the two sets of data(collection 1 and 2) and if it finds an elements that are equal, only add 1 of those elements to the new collection. Otherwise, add all of the non-equal elements to the new collection.
Here is what I made, but I know that it isn't working. There is a call to one of my other methods findBook that I will post.
public BookCollection merge(BookCollection c1,BookCollection c2){
//use this. operator to grab other vars
BookCollection cNew = new BookCollection(cNew);
for(String s1: c1)
if (s1.equals(c2)) {
cNew = c1;
}
cNew = c1 + s1;
}
Annddd
private int findBook(String isbn){
// iterate all the Book elements in the collection array
for(int i = 0; i <= collection.length; i++){
// check if the current book isbn matches the one provided argument
if (collection[i].getIsbn().equals(isbn))
return i;
}
return -1;
}
The solution should be far shorter than that.
I'll give you some tips because the idea is not give plain solutions and this question I'm pretty sure is homework.
If the question is homework add 'homework' tag
Tips:
Your main method doesn't have any loop. How are gonna iterate over the collections?
Books as objects they are should have an equals method. If that method is correctly implemented (you should define what is a method begin equals to another), then you just can compare b1.equals(b2)
Collections have contains method to check if it contains (by using equals) other book
Math.min method calculates the minimum between two integers or doubles (there are two versions)
Also, to be complete, if your collections are of a certain type your books should implement hashCode in a compatible way with equals (but my guess is you don't know what hashing is yet, and you'll not use that kind of collections)
So first of all: devise an algorithm. The simpler the better. In plain English.
Just then try to implement that. You'll see the code is much simpler and tidy if you try to program a previous well thought concept.
Edit:
Ensure to know what a Collection is in Java world (tip: is a general interface implemented by several distinct more specific classes).
And don't use the word array unless you are using real arrays (and given your exercise proposal it doesn't seem you need it).
Let's say I have an entity called Customer and a helper class called CustomerMapper which gets the values from the form. Then I'm sending this CustomerMapper to the service layer where I extract the values from the getters and add a new Customer into the database.
However now I need to iterate over a List<Customer> and check whether a customerID is contained in another ArrayList<CustomerMapper>. I read that the .contains() method calls .equals() on the element.. So i was wondering if it would be correct for me to implement equals() on Customer whereby I will be sending an object of type CustomeMapper and I will be comparing customer.getId() with customerMapper.customerId().
If the answer is no, please do elaborate why it is so.
EDIT:
This is what I've come up with. I've iterated through both arralists and created Map<Long, Customer> and Map<Long, CustomerMapper>. Basically I need to delete all Customer whose ids are not contained in the Map<Long, CustomerMapper>. now i iterate over Map<Long, Customer> and call Map<Long, CustomerMapp>.contaisKey(currentElement). Is this a good solution because this way I have three for loops.
It wouldn't make sense to do this by implementing an equals() method, simply because the two objects won't be equal.
Just extract the id and do a check if CustomerMapper has the same one.
No, you should only implement equals to return true for equal objects. Study the Javadoc on equals, especially what properties the relation imposed by it must possess, such as symmetry, transitivity and reflectivity. I think your intended implementation would fail on at least the first two, maybe also the last one. You'll just have to write an explicit loop that tests all members for your criterion.
Regarding your current solution:
Isn't it overkill to use maps? I propose simply collecting the ids from CustomerMappers into a HashSet and using that set in the filtering loop on Customers. BTW your idea to use equals does not reduce the time complexity; the loops would only be hidden behind the contains method call, resulting in total O(n2) complexity. The solution with a Set/Map is in fact less complex due to O(1) hash lookup: the overall complexity is only O(n).
I wouldn't do this. Think about any other use of collections, e.g. java.util.Set. You could run the following code:
Set<Object> customerLikeObjects = new HashSet<Object>();
customer.add(new CustomerMapper(13));
if (customer.contains(new Customer(13))) {
// Run some code
}
The condition should check if a customer by ID 13 is already in the set and then run some code. But in fact, the Set doesn't contain the customer, but some "similar" object. As a matter of fact, you probably wouldn't even mix the two object types in a single set, would you?
While this "clever" solution seems to fix your problem, it would be very confusing, eventually. In fact, anything that is "clever" but just somehow doesn't feel right is always a very bad idea.
As the "equals" method signature looks like public boolean equals(Object that) you can implement comparison between objects of any type. Probably you'll have to add something like
if (that instanceof CustomerMapper){
//do your comparison here
}
in your method implementation.
instanceof is rather a slow one, though.
The reason it would be 'wrong' to override equals in that way is that it would break the general contract of equals and could lead to weird, subtle (or weird, obvious) bugs
If you look at the source of ArrayList contains() calls indexOf() which iterates over the list. So you're not taking a performance hit (and it it would arguably be more readable) to write a comparison method yourself.
Assuming both Customer and CustomerMapper have a getId() method
public Boolean containsCustomer(List<CustomerMapper> customerMappers, Customer customer) {
if (customer == null || customerMappers == null || customerMappers.size() == 0) {
return false;
}
for (int i = 0; i < customerMappers.size(); i++) {
if (customer.getId().equals(customerMappers[i].getId())) {
return true;
}
}
return false;
}
Lets say I have a list and I am trying to look up a Class element in it, from which I only know one (unique) attribute.
public static List<Achievement> listAchievements;
String idAchievement = "5764e35";
This is obviously not working
listAchievements.indexOf(idAchievement );
Neither is this
Achievement ach(idAchievement);
listAchievements.getIndexOf(ach);
and the workaround is not pretty
for (Achievement achievement : listAchievements) {
if (achievement.resourceID().equalsIgnoreCase(idAchievement)) {
// STUFF
break;
}
}
What you have isn't a workaround, it's the solution.
You could abstractify it with lambda-like behavior, and this and that... but in the end, if you're trying to search a list for an element that has a given attribute, there's nothing you can do but to iterate over the list until you find an element with that given attribute.
If you need to find Acchievments by ID more directly, a Map<String,Achievement> might be a better choice if the IDs are unique (which you say they are).
There is no other way than to loop over the elements until you find the one you're looking for. You could use Guava's support for predicates:
Achievement a = Iterables.find(list, new Predicate<Achievement>() {
#Override
public boolean apply(Achievement input) {
return input.resourceID().equalsIgnoreCase(idAchievement)
}
});
but the end result is the same.
Or you could maintain a separate Map<String, Achievement> in addition to your list, or use a LinkedHashMap<String, Achievement> instead of your list, which would achieve O(1) search instead of O(n).
1) you have to sort your list using static void sort(List,Comparator).
2) use static int binarySearch(List,Key,Comparator).
These two method are of java.util.Collections
If you only have a list there's not much more to do. But if this is something that is done often you may want to consider creating a HashMap or similar instead (from achievementId to achievement).
To make such efficient you'll either have to use Map of idAchievement to Achievement, or make sure your collection is sorted by idAchievement attribute and then use Collections.binarySearch().
This question already has answers here:
How to return multiple values? [duplicate]
(3 answers)
Closed 3 years ago.
This is a small issue, as I could easily whip up a pair class to do the job. I don't really want to do this though, and I feel like there should be some simple, built-in, java-like way of returning two values. What do you guys is the best, simplest way of doing this? Arrays? Some other data structure?
As far as I know, there is unfortunately no built-in representation of a pair in Java (and I certainly wish there was). Personally, when I code a project where I find that a pair class often would be useful, I create a generic Pair<T, U> class (which is probably what you were thinking of). Returning an array is a fast and simple way, but you might come to regret it later, because people who use your method will wonder whether the method might at some point return more than two values.
Whichever solution you choose: whenever you feel that you need a Pair, you should consider whether the time saved today by using e.g. a generic Pair class really is worth the loss of information to the next person who reads the code (and that person may well be you in six months). Writing a separate class for the return type takes more time now, but it would convey more information to those that use your method (namely, it tells the users what the return value represents, and contains useful member names for the two values). If it is a non-public method that is used only a few places, though, a Pair is more acceptable.
Using a container class is the easiest way.
public class Pair<T, U> {
public final T t;
public final U u;
public Pair(T t, U u) {
this.t= t;
this.u= u;
}
}
The closest thing I've seen to a "pair" in the standard libraries are the Map.Entry interface and the AbstractMap.SimpleEntry and AbstractMap.SimpleImmutableEntry classes that implement it.
If both objects are the same class an array is easier to use.
Apache Commons Lang3 provides an abstract Pair class with a couple implementations including ImmutablePair and MutablePair.
Three approaches, all not so great:
Roll your own Pair<A, B>. You said you didn't want to do that.
Return a Object[]. This is not type safe.
Mimic out variables or pointers by supplying single element arrays as parameters.
An example of #3:
public boolean getUserDetails(String userId, String[] lastName, String[] firstName, Date[] dob) {
assert lastName != null && lastName.length == 1;
assert firstName != null && firstName.length == 1;
assert dob != null && dob.length == 1;
...
}
The third option makes life painful for the caller.
So like I said, no nice solution.
As an aside, Scala uses various Tuple classes (up to 21-tuple, from what I remember) to help you with this.
There is a pair class in JavaFX, but you shouldn't use it. What you SHOULD use is something like this:
// We've skipped imports and package declarations
public final class YourClass {
/* Assume there is a bunch of stuff here */
// I don't know what method you're using, so forgive the silly example
public YourClass.Pair sillyExampleOfPairs(String someString) {
return new YourClass.Pair(someString, someString.length() * 13);
}
#Value // Lombok annotation.
public static class Pair {
String text;
int integer;
}
// this is an even more succinct possibility
#Value public static final class ShorterPair {String text; int integer}
}
While the name Pair here is obviously not that well chosen, and you should choose a more descriptive name, the obvious ways this will work (the fields are final private and you have a getter on each, because of the annotation), should not be lost on you. And while yes, this is slightly more wordy than using Pair, it's much more robust. What if you do need to add an extra parameter to the return value? You "only" need to change this class then. And you can update all the relevant JavaDocs immediately, which is also nice. If you have to change types, they would both entail similar amounts of work.
As long as you're only adding stuff, the old getText() and getInteger() methods would keep working as they did before. You also avoid having to add Yet Another Dependency to your projects. It's not a big win. Having Pair available is nice for prototyping, but it's not nice for later.
My final theoretical CS-y argument is that Pair is the same type as Pair. But if you have a Phonebook.Entry (with String and int) and say, Inventory.Item (with a name and a number of items we currently have inventoried), these two are very distinct types, which do very distinct things. You can't put one into the other. This is a Good Thing.
It's also much clearer for us poor bastards that have to go and debug your systems to see something like "com.name.project.something.something.Phonebook.Entry" in a stack trace than "org.apache.commons.lang3.tuple.Pair". One of these tells me WHAT I'm supposed to be looking at, and gives me some info on WHY I'm seeing a pair. The other says... nothing.
Now you might not care that you have to type for 3 extra seconds to save me 3 minutes. But I choose to believe in the goodness of your heart, and the nobility of your soul. Therefore, do the right thing.
Write a small static class instead.
I have been told by experts that when faced with the question of pairs, one of two things is true:
You need to rethink your structure (this blunt answer doesn't help anyone)
You need to build your own class to hold the pair
I would suggest that the second case is not all that abnormal. However, if what you are doing seems too trivial for introducing a new class, then using a Map could work, as others have suggested. If you are simply sending a single response back, then a Map seems like a bit much.
If a list of pairs sounds like it would work, and you need to maintain order, you could try a LinkedHashMap so that order is maintained.
if both are integers then I would advise a java.awt.Point but otherwise just create a container class with two objects x and y
Some observation of mine:
Array is bulit-in, fast and easy to use, although imposible to expand its capacity. What if you want 3 values to be returned after 3 months?
ArrayList/other colletions can be good, allows you to increment the capacity(initially 10).
Note that Vector can be overkill in comparison to ArrayList when you only want to store 2 values to be fetched later. Map also can be good because it's always sorted and ordered.
Some user-defined class: maybe an option if is meaningful(means that the data returned is important-ish to be a Java Bean), and you want to store more than just 2 integers into it. Readibility is better in case you add more notes in its Javadoc. Can be expanded as you like, just add fields in this class. Slower, but safer.
class Collection
{
int sNo;
String sessionID;
int noOfDependency;
int noOfRejection;
int totalValue;
Collection(int sNo, String sessionID, int noOfDependency, int noOfRejection, int totalValue)
{
this.sNo = sNo;
this.sessionID = sessionID;
this.noOfDependency = noOfDependency;
this.noOfRejection = noOfRejection;
this.totalValue = totalValue;
}
}
public class DependencyStack {
/** Creates a new instance of DependencyStack */
public DependencyStack()
{
LinkedList lList = new LinkedList();
lList.add(new Collection(1,"a",0,0,0);
lList.add(new Collection(2,"b",0,0,0));
for(int i=0;i<lList.size();i++);
System.out.println(lList.getFirst());
}
I am not able to view the individual data. For e.g. if i want to view all sno "serial nos.", how can i do that.. i have tried lot of options, please helpp...
Use the standard API library as God, um, I mean Gosling intended.
Seriously, those have been tweaked, optimized and bugfixed a hundred times over - you're very unlikely to do any better.
In fact, java.util.LinkedList already has a size counter. But ArrayList is better for most cases (exception: if you often need to remove elements while traversing).
BTW, 500-1000 elements is chump change. It's nothing. You've wasted more time asking this question than your program would running an O(n) implementation a million times.
Edit: To store more than one piece of data in one node or list slot, write a class that has your data as fields (private and exposed via set and get methods if you want it to be particularly "clean") and put instances of that class into the list.
Is there a reason you don't want to use a built in class, like List?
these classes take care of all the implementation details for you. look at java.util.List
Java's LinkedList class keeps track of the size as you add/remove elements. Getting the size is free, you don't traverse the list. Don't worry about multiple pieces of info in a node, just put all you info in an object.
I know this is homework, but you really shouldn't seem so demanding and consider posting some code that illustrates you problem. We're not doing you work for you.
System.out.println(lList.getFirst());
lList.getFirst() returns an object of type Collection (you should use a better name BTW).
So you have to access to lList.getFirst().getSerialNumber() for example (and you also will have to write the method getSerialNumber() in your Collection class...