As an exercise (note that I am a programming student, but this is an exercise to satisfy my own curiosity, not for a graded assignment) in using instance variables, I would like to create an unspecified number of instances of a class and assign a unique name to each. My idea would be to make a loop such as:
int i=1;
while (! response.equals("quit")){
SomeClass object_i = new SomeClass();
i++;
...
}
This would allow the program to create as many instances of SomeClass as needed by the user, then be able to refer back to instance variables in each one such as:
for (i=1; i <= count; i++){
sum += object_i.nonStaticInstanceVariable;
}
There is a suggestion for unique identifier names using AtomicLong at this thread:
java for loop executes too fast gives System.currentTimeMillis() duplicate
but I am unsure of how I would refer to instance variables in particular objects created using this method. Can anybody suggest a way to do what I'm trying to do in Java?
Many thanks.
In your first for-loop, you're creating instances of SomeClass, but you're not doing anything with them. What you want to do is gather them up in some kind of collection, so you can refer to them later, like this:
int i=1;
List<SomeClass> classes = new ArrayList<SomeClass>();
while (! response.equals("quit")){
classes.Add(new SomeClass());
i++;
...
}
Now you can loop through your collection and do something useful with them:
for (SomeClass someClass : classes) {
sum += someClass.nonStaticInstanceVariable;
}
I would use a map and a universally unique identifier (UUID). See java.util.UUID for an example.
Map<UUID,SomeClass> map = new HashMap<UUID,SomeClass>();
for (int i=0;i<1000000;i++) {
UUID key = UUID.randomUUID()
map.put(key, new SomeClass());
}
Now if the user has a UUID then they can get a reference to the appropriate SomeClass
lol, you must really just be starting.
Read this- http://download.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html
Most of what you have makes sense, but you need to do-
SomeClass myObject[i] = new SomeClass();
EDIT: Other people's options will work too, but you should learn to do it this way first.
You can't create instance variables at runtime (short of compiling and loading a new class)
Use an array or a Map for this
(Or use a dynamic language like Groovy that runs on the JVM, which internally will use a map-like structure)
I think you would just want to use some sort of collection such as an array or arraylist.
List list = new ArrayList();
int i=1;
while (! response.equals("quit"))
{ list.add(new SomeClass());
i++;
}
It could then be accessed by getting index in the ArrayList
list.get(index);
Related
the object of this specific function is to create a list of (competitor objects ) Using 2 lists containing time and names.
note that this is a trail to convert from object oriented to functional programing , so its actually a record rather than an object.
my initial trial using a sort of recursion
public static List<Competitors> makeObjects(int[] time, String[] name){
if (counter > name.length){
return racers;
}else{
Competitors racer= new Competitors(name[counter],backToTime(time[counter]));
racers.add(racer);
return makeObjects(++counter,racers,time,name);
}
and my try after discovering i can use streams
public static List<Competitors> makeObjects(int[] time, String[] name){
List<Competitors> racers = new ArrayList<Competitors>();
IntStream.range(0,time.length).mapToObj(i-> ).collect(new Competitors(name[i] ,backToTime(time[i])))
}
Your second approach, makeObjects(), is the functional approach.
Where you go wrong is that you are creating the Competitor objects in the wrong place; you map each i to a new Competitor. Then in the collect() call, you specify what type of collection. In your case, it would be Collectors.toList() or Collectors.toSet(). There is no need to create an ArrayList; just assign the IntStream... to List<Competitor> racers.
Note that you should probably guard this method by first asserting that the arrays are the same length.
Also note that your class should be named Competitor, not Competitors; and makeObjects would be more descriptive as createCompetitorsList.
In Java I have the following code
List<Integer> myList = new ArrayList<>();
for (int i=0;i<9;i++) {
myList.add(i);
}
Integer sum = 0;
myList.forEach(i -> {
sum = sum + i; // does not compile, sum needs to be final or effectively final
});
for(int i : myList) {
sum = sum + i; //runs without problems
}
My question is, why is it exactly that I cannot change the value of sum from within the lambda? It does the exact same thing as the for loop down below, or am I wrong? Interesting is also the fact that if I declare the Integer sum outside of the main method as static, it works as well. Can anyone explain me why?
EDIT: In another similar question Does Java 8 support closures, the answer seems to be :
it is a combination of backwards compatibility and project resourcing constraints.
However I still cannot understand why it works if I make sum an array or if I declare it outside of main. I would also like to understand what is the difference between the myList.forEach and the for loop below, why the one works and the other one doesn't.
Try with:
final Integer[] sum = new Integer[1];
sum[0] = 0;
myList.forEach(i -> {
sum[0] = sum[0] + i;
});
Since lambda is actually a syntactic sugar for initializing an anonymous class (and overriding a method).
It's the same as if you have written:
final Integer[] sum = new Integer[1];
sum[0] = 0;
myList.forEach(new Consumer() {
public void accept(Integer element) {
sum[0] = sum[0] + element;
}
});
The variable that comes from outer scope and that you use within inner scope must be final (in this example sum). That is simply because Java does not support closures. Therefore, outer variable must be marked as final. Since Integer itself is immutable (if you declare it final, you cannot change it anymore), you have to use a wrapper object or an array (as I did).
You can find more useful info here:
Why are only final variables accessible in anonymous class?
Cannot refer to a non-final variable inside an inner class defined in a different method
Not exactly the answer you are looking for, but in most scenarios you won't need to modify that inside the lambda. This is because it's not idiomatic for lambdas to be state-changing in a proper functional style.
What you can do to achieve your result is use any of the higher-level functions provided to mask the "accumulator", and then assign:
sum = myList.stream().mapToInt(x->x).sum();
A lambda is basically an anonymous class. You can only access final local variables from anonymous class.
What you need is a wrapper class that can modify its content. For a quick hack, you can use AtomicInteger in this case:
AtomicLong sum = new AtomicLong(0);
myList.forEach(i -> {
sum.addAndGet(i); // does not matter getAndAdd or addAndGet
});
sum.get(); // to get the value
Another way is, if you are using Intellij IDEA, the IDE can suggest you to transform the variable into final one element array (as in darijan's answer).
Before beginning, I think that this question has a very simple answer that I'm just overlooking. I figured a few more eyes on the question at hand will be able to point out my problem fairly quickly.
I have two ArrayLists that I want to compare and remove duplicates from each of them. The first ArrayList is an ArrayList of older information where as the second ArrayList contains the new information.
Like so
ArrayList<Person> contactList = new ArrayList();
contactList.add(new Person("Bob");
contactList.add(new Person("Jake");
contactList.add(new Person("Joe");
ontactList.add(new Person("Rob");
ArrayList<Person> updatedContactList = new ArrayList();
updatedContactList.add(new Person("Bob");
updatedContactList.add(new Person("Jake");
updatedContactList.add(new Person("Joe");
updatedContactList.add(new Person("Phil");
My Person class is very simple, created solely for this example
public class Person {
private String name;
public Person(String a_name) {
name = a_name;
}
public String getName() {
return name;
}
}
So, using the above examples, I want to remove all duplicates. I'm trying keep it to just the two ArrayLists if possible, but am willing to do a deep clone of one of the ArrayLists if I have to.
So I want the resulting ArrayList to have the following information in it once the comparison is done
contactList //removed Person
- Rob
updatedContactList //new Person
- Phil
Here is the code I've put together
for(int i = 0; i < contactList.size(); i++) {
for(int j = 0; j < updatedContactList.size(); j++) {
if(contactList.get(i).getName().equals(updatedContactList.get(j).getName())) {
//removed friends
contactList.remove(contactList.get(i));
//new friends ---- only one at a time works
//updatedContactList.remove(updatedContactList.get(j));
}
}
}
I'm only able to remove a Person from one of the ArrayLists in the above loop otherwise I get incorrect results.
So my question is, is there an easy way to remove the duplicated elements from both ArrayLists? If so, how do I go about it.
I realize that I could probably deep clone the updated ArrayList and just remove the objects from that one, but I'm wondering if there is a way without having to clone it.
I also realize that I could just stuff all the elements into a Set and it would remove the duplicates, but I want to keep the 'removed' and 'new' Person objects separate.
What you really have is not lists, but sets: model both the old and the new contacts as a Set. Also implement equals and hashCode for your Person class to ensure proper operation.
Once you have that, you'll be able to write one-liners to calculate the set differences (which is what you need):
final Set<Person> contactsBackup = new HashSet<>(contacts);
contacts.removeAll(updatedContacts);
updatedContacts.removeAll(contactsBackup);
Note that this involves making one more copy, but it is not a deep copy—only references are copied. This is a very leightweight operation and you should not worry about its impact.
If, for some reason not at all obvious to me, you really need lists, the same code will work for them, too (List also defines removeAll), but you will have to live with O(n2) complexity this operation entails for lists.
Override equals() and hashCode() in your Person class and simply do:
Set<Person> temp = new HashSet<>(contactList);
contactList.removeAll(updatedContactList);
updatedContactList.removeAll(temp);
temp.clear(); // not necessary if this code is in a method
Create a Set and addAll from both the ArrayLists.
Set<Person> set = new ArrayList<Person>();
http://docs.oracle.com/javase/6/docs/api/java/util/Set.html
This is a one line elegant solution making use of the Java 8 capabilities
public static final <T> void removeCommonEntries(Collection<T> a, Collection<T> b){
b.removeIf(i -> a.remove(i));
}
I use to put this solution in a custom CollectionUtils.
In this case use Set and not List (this is used if you are getting data from DB using say Hibernate) if possible. Then you can override equals and hashcode method in person class so that while adding required comparisons can be made and duplicates can be taken out. LinkedHashSet can be used as Lists can become slow as data in it grows.
I understand the idea behind a hash table, but the implementation is getting frustrating. I have done some reading and gotten mixed answers. I have read that I could implement a generic array of objects as follows:
TableContainer[] classTable =
(TableContainer<Object,Object>[]) new TableContainer[256];
where tableContainer is:
class TableContainer<key,val>{
Object key = null;
Object val = null;
}
The problem I am having is that when I try to pass the following code in a function:
classTable[i].key = x
I get a null pointer exception. I understand creating generic arrays in java gets messy because of type erasure but I thought the above implementation would work. Is there any way to create a list or array of generics to be utilized as a hashtable? (no hashtable/hashmap classes permitted)
You still have to initialize the object references inside the array before you can use them. Like so
tableContainer[] a = new tableContainer<Whatever, SomeClass>[SIZE];
for ( int i = 0 ; i < a.length; i++ ) {
a[i] = new tableContainer<Whatever, SomeClass>();
}
And of course, you must initialize the array to a size greater than 0, unlike you have in your example.
First of all you are creating an empty array:
new TableContainer[0]
and since you cannot resize arrays over time, it doesn't have much sense. Providing that you actually create an array of some positive size, you must remember one thing: you created an array of references. And by default each array is initialized to default (zero) values, which happens to be null for references.
Thus you need something like this:
classTable = new TableContainer[8];
classTable[0] = new TableContainer();
//...later
if(classTable[0] != null) { //will pass for [0], but not for [1]
classTable[0].key
}
i am php developer just started at java i want to declare dynamic variables inside a loop and for that i have to append the loop value to varaible name this is what i want .
I would like to make statement like this
for (i=1; i<6; i++)
{
String new_variable_ + i;
}
the above code does not work in java how to do it ?
what you are trying to do is not possible in java ... this language is
not that lose like php..its a type strict language
Variable declarations are declared to be static identifiers and cannot contain any computed values in java (and i venture to say this would be true in any statically typed language).
You say you can't find an associative array. Have you seen the java.util.Map interface (and it's implementations)? It is by definition an associative array:
Wikipedia: In computer science, an associative array, map, or dictionary is an abstract data type composed of a collection of (key,value) pairs, such that each possible key appears at most once in the collection.
Like I said in the comment, there's no dynamic variable in Java. At best you can do this:
HashMap variableMap = new HashMap<String,String>();
for (int i = 1; i < 6; i++) {
variableMap.put("new_variable_" + i, "some variable value");
}
Then to access them, you do:
String value = variableMap.get("new_variable_2");
Or to update it, you do:
variableMap.put("new_variable_2", "new value");
If you just want to use a string version of i within the loop, you need:
for (int i=1; i<6; i++)
{
String new_variable_ = "" + i;
//use new_variable here.
}
If you're looking for something different, I'll need some more details. Good luck!