I want save an object multiple times, the code below can not work:
for(int i = 0; i < 5; i++) {
repository.save(object);
}
Then I change the source to:
List<SomeObject> objectList = new ArrayList<>();
for(int i = 0; i < 5; i++) {
objectList.add(object);
}
repository.save(object);
But it also can not work, It only save the object one time to database.
Maybe because it point to one instance, but I want to know if there is an easy way to save an object multiple times?
Thank you!
It saves only 1 time the object because you are using the same instance every times.
So the first time you use object, so now it has an ID, then you use object again, but as we said it has an id so instead to save it, yours program update it inside you db.
For example if you do this:
for(int i = 0; i < 5; i++) {
repository.save(new Object());
}
Or if you have a list of Objects, like
List<SomeObject> objectList = new ArrayList<>();
for(int i = 0; i < 5; i++) {
objectList.add(object);
}
you could do this:
repository.saveAll(objectList);
Now you find 5 rows inside your table
I am not familiar with Spring data and might misunderstand the problem but generally there is no point to save the same object many times.
You need to explicitly create a clone/copy (or so) of an instance and save all these instances separately if you need multiple instances in database.
For example add creating new instance in a loop that saves the object.
Using the constructor, you can save same object multiple time:
Repository.save(new object(String name,String age));
Related
In my app, I have a method that accepts an ArrayList of ID's and returns a RealmList of Machines belonging to these IDs.
public RealmList<Machine> getMachinesById(ArrayList<Long> machineIds) {
RealmList<Machine> machines = new RealmList<Machine>();
for (int i = 0; i < machineIds.size(); i++){
Machine m = getMachineById(machineIds.get(i));
if (m != null) {
machines.add(m);
}
}
return machines;
}
The getMachineById() function just finds the correct machine for a specific id.
I want to filter this output some more, however, when I try to get the RealmQuery by doing .where(), I get an Exception telling me I should put this RealmList in 'managed mode'.
Caused by: io.realm.exceptions.RealmException: This method is only available in managed mode
at io.realm.RealmList.where(RealmList.java:425)
I'm aware that I get this error because this list is standalone, and not managed by Realm.
It is probably important to add that this function will be called quite a lot, since it is triggered every time some list in my app refreshes. This would mean that (if possible) every time I'm creating a new managed RealmList.
My questions:
Is there any way to let this RealmList be managed by Realm?
If this is possible, is it a problem that this function is being called pretty often
Is there any other (preferred) way to achieve this (List of IDs > RealmResults/RealmQuery)
Is there any way to let this RealmList be managed by Realm?
Yes. There is. But the point of having RealmList is it should be a field of an RealmObjects. eg.:
public class Factory {
RealmList<Machine> machineList;
// setter & getters
}
Factory factory = new Factory();
RealmList<Machine> machineList = new RealmList<>();
// Add something to the list
factory.setMachines(machineList);
realm.beginTransaction();
Factory managedFactory = realm.copyToRealmOrUpdate(factory);
realm.commitTransaction();
Managed means it has be persisted Realm.
If this is possible, is it a problem that this function is being called pretty often
Depends, if you don't need to persist them again, see answer 3.
Is there any other (preferred) way to achieve this (List of IDs > RealmResults/RealmQuery)
In your case, maybe you can use ReaulResults instead? eg.:
RealmQuery<Machine> query = realm.where(Machine.class);
for (int i = 0; i < machineIds.size(); i++){
if (i != 0) query = query.or();
query = query.equalTo("id", machineIds.get(i));
}
RealmResults<Machine> machines = query.findAll();
At work, we have to generate a report for our client that changes its parameters several times during the week.
This report is generated from a single table on our database.
For example, imagine a table that has 100 columns and I have to generate a report with only 5 columns today, but tomorrow I have to generate with 95 of them.
With this in mind, I created a TO class with all the columns of the specified table and my query returns all columns (SELECT * FROM TABLE).
What I'm trying to create is a dynamic form to generate the report.
I first thought on create a simple frame with a list of the columns listed as check boxes and the user would select the columns that he wants (of course with a button to Select All and another to Deselect All).
As all of the columns have the same name as the attributes of the TO class, I developed the following code (I have Google this):
Class c = Test.class;
for(int i = 0; i < listOfAttributes.length; i++)
{
auxText += String.valueOf( c.getMethod( "get" + listOfAttributes[i]).invoke( this, null ) );
}
Is this the better way to do what I need to?
Thanks in advance.
Obs.: the getters of the TO class have the pattern "getAttribute_Name".
Note: This question is different from the one where the user is asking HOW to invoke some method given a certain name. I know how to do that. What I'm asking is if this is the better way to solve the problem I described.
My Java is a little more limited, but I believe that's about as good as you're going to get using reflection.
Class<?> c = Test.class;
for (String attribute : listOfAttributes) {
auxText += String.valueOf(c.getMethod("get" + attribute).invoke(this, null));
}
But since this sounds like it's from potentially untrusted data, I would advise using a HashMap in this case, with each method explicitly referenced. First of all, it explicitly states what methods can be dynamically called. Second, it's more type safe, and compile-time errors are way better than runtime errors. Third, it is likely faster, since it avoids reflection altogether. Something to the effect of this:
private static final HashMap<String, Supplier<Object>> methods = new HashMap<>();
// Initialize all the methods.
static {
methods.set("Foo", Test::getFoo);
methods.set("Bar", Test::getBar);
// etc.
}
private String invokeGetter(String name) {
if (methods.containsKey(name)) {
return String.valueOf(methods.get(name).get());
} else {
throw new NoSuchMethodException();
}
}
It might sound like a major DRY violation to do so, but the repetition at least makes sure you don't wind up with unrelated getters accidentally called.
Class c = Test.class;
for(int i = 0; i < listOfAttributes.length; i++)
{
auxText += String.valueOf( c.getMethod( "get" + listOfAttributes[i]).invoke( this, null ) );
}
You can do this somewhat more elegantly via Java Beans, the Introspector, and PropertyDescriptor, but it's a little more long-winded:
Map<String, Method> methods = new HashMap<>();
Class c = this.getClass(); // surely?
for (PropertyDescriptor pd : Introspector.getBeanInfo(c).getPropertyDescriptors())
{
map.put(pd.getName(), pd.getReadMethod();
}
//
for (int i = 0; i < listOfAttributes.length; i++)
{
Method m = methods.get(listOfAttributes[i]);
if (m == null)
continue;
auxText += String.valueOf(m.invoke(this, null));
}
Is this usage of elements of an ArrayList:
for(int i=0; i<array_list.size(); i++){
Object obj = array_list.get(i);
//do **lots** of stuff with **obj**
}
faster than this one:
for(int i=0; i<array_list.size(); i++){
//do **lots** of stuff with **array_list.get(i)**;
}
It depends on how many times array_list.get(i) is called in the second code. If it is called only once, there is no difference between both methods.
If it's invoked multiple times, saving the value in a variable may be more efficient (it depends on the compiler and the JIT optimizations).
Sample scenario where the first method may be more efficient, compiled using Oracle JDK's javac compiler, assuming the list contains String objects:
for(int i=0; i<array_list.size(); i++){
String obj = array_list.get(i);
System.out.println(obj);
if(!obj.isEmpty()) {
String o = obj.substring(1);
System.out.println(o + obj);
}
}
In this case, obj is saved as a local variable and loaded whenever it is used.
for(int i=0; i<array_list.size(); i++){
System.out.println(array_list.get(i));
if(!array_list.get(i).isEmpty()) {
String o = array_list.get(i).substring(1);
System.out.println(o + array_list.get(i));
}
}
In this case, multiple invokation for List.get are observed in the bytecode.
The performance difference between getting once and a local variable is almost always neglible. But... if you insist on doing it the hardcore way, this is the fast way to go:
ArrayList<Object> array_list = ...
// cache list.size() in variable!
for (int i=0, e=array_list.size(); i < e; ++i) {
// get object only once into local variable
Object object = array_list.get(i);
// do things with object
}
It caches the lists size into a local variable e, to avoid invoking array_list.size() at each loop iteration, as well as each element in the loop to avoid get(index) calls. Be aware that whatever you actually do with the objects in the loop will most likely be by orders of magnitude more expensive than the loop itself.
Therefore, prefer code readability and simply use the advanced for loop syntax:
ArrayList<Object> array_list = ...
for (Object object : array_list) {
// do things with object
}
No hassles, short and clear. Thats worth far more than a few saved clock cycles in most cases.
I have an 8x8 board with 64 four fields, each being a LinearLayout.
Each LinearLayout has its ID like (field1, field2... field64).
Now I want to modify the background of each field later in my program but I don't know how to retrieve the layout I want to modify. I wanted to put all of them in the Array but it's not working.
private LinearLayout[] fields = new LinearLayout[65];
this.fields[field_id].setBackgroundColor(colour);
Another approach:
for (int i=1; i<65; i++) {
findViewById(R.id.field+i).setBackgroundColor(Color.WHITE);
}
It does not work as well (obviously). How should I approach this?
You can add them to a list, like this:
List fieldList = new ArrayList(64);
fieldList.add(R.id.field1);
fieldList.add(R.id.field2);
fieldList.add(R.id.field3);
// etc.
fieldList.add(R.id.field64);
Or use any other method to create such a list/array. It is a bit tedious, adding all fields like this, but it provides a usable list that can be used in loops.
It is also possible (I think), to renumber the ids of the fields (in R.java). If you make them subsequent, you can use the method you tried in the example code of your question. I do not not for sure whether these IDs stay the same when R.java is re-generated... If not, this method is not usable!
Make an Array with your ids.
int[] ids = {R.id.field1,R.id.field2...}
for (int i=0; i<ids.lenght; i++) {
findViewById(ids[i]).setBackgroundColor(Color.WHITE);
}
OR
ViewGroup viewgroup = findViewById(R.id.parentview);
for(int i = 0; i < viewgroup.getChildCount();i++)
{
View child = viewgroup.getChildAt(i);
}
You can access them this way, a tiny bit slower but doubt you will have a problem with it:
for (int i=1; i<65; i++) {
int id = getResources().getIdentifier("field" + i, "id", getPackageName())
findViewById(id).setBackgroundColor(...);
}
Sounds like a lot of work adding them in xml(I assume?) like that though. Preferably you would add them by code and then just save them in an array.
What I want is to create multiple view in for loop
example
for(int i =1; i<5; i++){
GridView view = new Gridview(this);
}
But It creates 5 gridview with the same name.. so in future i can't set different option to a specific gridview. How do I get, that gridivew created in a loop get view + i name
Use a List
List<GridView> views = new ArrayList<GridView>();
for(int i = 1; i < 5; i++) {
views.add(new GridView(this));
}
Then you can get your views with
views.get(i);
Also, in your example, when a step of the for loop ends, the reference to that object is lost as the scope in which they were created is left. With no reference to the objects, the Garbage Collector comes in and frees that memory, deleting the objects.
So, you won't be able to access not even the last object created. If you modify the code like this, at the end of this code you will have only the last object instantiated:
GridView view;
for(int i =1; i<5; i++){
view = new Gridview(this);
}
Now the object exists in the scope you are in at the end of the code snippet. But only one object really exists.
So, the solution is to store the objects in some additional structure: an array if you know precisely how many objects you want, or some self dynamically allocated collection structure. And you have examples of both in the other answers.
Added: What you are actually asking for (to dynamically build the object's reference name) is called metaprogramming. I don't know if it is possible in Java, but here is an example of this done in PHP:
class Object {
function hello(){
echo "Hello \n";
}
}
for($i =1; $i<5; $i++){
$name = "view".$i;
$$name = new Object();
}
$view1->hello();
$view2->hello();
$view4->hello();
Here is runnable code: http://codepad.org/bFqJggG0
Use a List of GridViews.
List<GridView> grids = new ArrayList<GridView>();
for(int i =1; i<5; i++){
grids.add(new Gridview(this));
}
I think this code will create 5 GridViews, 4 of which will become immediately available for Garbage Collection as your code no longer has a reference to them.
If you create them in a loop, then I think I'd be looking to store them in a data structure such as a List or Map and then accessing them via an index or key.
i think you can do something like this :
for(int i =1; i<5; i++){
GridView view = new Gridview(this);
view.setId(i);
}
and then , you can difference between all views
GridView[] view=new GridView[5];
for(int i=1;i<5;i++){
view[i]=new GridView(this);}
Now I think you can set specified options.