0

Situation

Well, this method is managing a conversion which accepts a list as a parameter, but definately doesn't look scalable.

List<Long> array_list_data= new ArrayList<>();

public void get_Data() {
    long0 = array_list_data.get(0);
    long1= array_list_data.get(1);
    long2= array_list_data.get(2);
}

Afterwards, it will create a different class with the long fields.

Problem

However, what if we have to expand this data to a 100 parameters on this list?

What I have done so far is:

List<Long> array_list_data= new ArrayList<>();

public void get_Data() {
    int k = 0;        
    long0= array_list_data.get(k);
    long1= array_list_data.get(k++);
    long2= array_list_data.get(k++);
}

Why incrementing k is not the right way to do it?

Machado
  • 14,105
  • 13
  • 56
  • 97
  • 1
    well, if you have 100 different variables, there's not much you can do, I presume. – vefthym Jul 31 '15 at 12:34
  • 2
    I disagree with the premise of your question. – Marko Topolnik Jul 31 '15 at 12:35
  • 1
    use `++k` instead of `k++` – Konstantin Yovkov Jul 31 '15 at 12:35
  • @kocko His first value is 0. He just needs to add `++` to the first call as well. – Marko Topolnik Jul 31 '15 at 12:35
  • If you had 100 different variables (which is *not* the Java way to hold data), the Java way to manage them would be with 100 different constants holding 100 different index values – blgt Jul 31 '15 at 12:37
  • instead of `k++` use `++k`. http://stackoverflow.com/questions/11629136/preincrement-postincrement-in-java – SatyaTNV Jul 31 '15 at 12:37
  • 5
    Your code is crying for classes and objects (and respect of naming conventions). Why don't you design a class holding all these attributes, instead of storing them as elements at random locations of a list? – JB Nizet Jul 31 '15 at 12:37
  • Use a Dictionary (or HashTable) for key-value indexing – ryanyuyu Jul 31 '15 at 12:37
  • 2
    @JBNizet This could actually be a conversion method where raw data is in array format. OP is doing just what you propose. – Marko Topolnik Jul 31 '15 at 12:37
  • @blgt `memory_version` and the other variables are static constants. – Machado Jul 31 '15 at 12:39
  • perhaps use a Map, to store variable name as key and variable value as value? – vefthym Jul 31 '15 at 12:40
  • 1
    @MarkoTopolnik right. I stand by my comment on naming conventions though – JB Nizet Jul 31 '15 at 12:46
  • @JBNizet this is just a conversion method, there's absolutely no randomness at all. – Machado Jul 31 '15 at 12:58
  • I'm going with @Jon Skeet 's answer. Although I extremely appreciate all the repercussion, suggests and alternative ways to manage this. I will have to change my code. – Machado Jul 31 '15 at 12:59
  • 1
    @Holmes: It would be helpful if you'd clarify your question in terms of the conversion - at the moment it looks like both the individual value fields (`max_memory` etc) and the list are fields within the class, which I view as poor modelling. If your code is actually a conversion which accepts a list as a parameter, and then creates a class with the various fields, that's a very different matter. – Jon Skeet Jul 31 '15 at 13:06
  • Thank you Jon. This is actually a class from my `android` application. I'm pulling data from the `List` to store each field later in a different class. – Machado Jul 31 '15 at 13:18

7 Answers7

7

k++ performs a post-increment. In other words, the value of the expression is the original value of k, and then k is incremented. It's still incremented before the method is called, but the value passed as the argument is the value before the increment takes place. In other words, a call of:

x = list.get(k++);

is equivalent to:

int tmp = k;
k = k + 1;
x = list.get(tmp);

So if you actually had:

memory_version = array_list_data.get(k++);    // Calls with 0, then k=1
mains_voltage_min = array_list_data.get(k++); // Calls with 1, then k=2
mains_voltage_max = array_list_data.get(k++); // Calls with 2, then k=3

then it would be fine, and equivalent to your first code. Your current problem is that you've actually got:

memory_version = array_list_data.get(k);      // Calls with 0, then k=0
mains_voltage_min = array_list_data.get(k++); // Calls with 0, then k=1
mains_voltage_max = array_list_data.get(k++); // Calls with 1, then k=2

However, I'd suggest that if you're modelling the data in a class using a collection as a field, you may well be better off with a separate field for each value. (You may create an instance of the class by extracting the data from a list, of course, but that's a different matter.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • What if there's a file containing the data in array format? This would be just the way to convert into the domain model. – Marko Topolnik Jul 31 '15 at 12:39
  • @MarkoTopolnik: I would probably read it from the file straight into the domain model: `memoryVersion = stream.readInt();` etc. Currently the OP has the list as a *field*, which doesn't seem like a good plan to me. – Jon Skeet Jul 31 '15 at 12:41
  • @JonSkeet what could possibly go wrong with listing it as a *field*? – Machado Jul 31 '15 at 12:46
  • But the code displayed does look like conversion into a domain model. Whether to do conversion straight away or later depends on a lot of factors beyond the scope of the question. – Marko Topolnik Jul 31 '15 at 12:47
  • @MarkoTopolnik: Possibly. I did say "may not be ideal". It's something the OP should at least *think* about. – Jon Skeet Jul 31 '15 at 12:51
  • @Holmes: The point is that having a list field is a lot less maintainable (IMO) than having a separate field per value, if you're trying to model "an entity with these various values" as a class. – Jon Skeet Jul 31 '15 at 12:52
  • But aren't `memory_version`, `mains_voltage_min`, and `mains_voltage_max` just the fields you are suggesting? Note that they are _not_ local variables. – Marko Topolnik Jul 31 '15 at 12:53
  • 1
    @MarkoTopolnik: If that's the case, then the class contains the same data in two different forms, which is even worse! If the question had presented a factory method or constructor *accepting* a `List` and returning a new instance, I wouldn't have made the comment. – Jon Skeet Jul 31 '15 at 12:56
  • The difference is major and the advice would be also completely different in that case. If the rest of the logic relies solely on the fields, then we are dealing with just the issue of the lifespan of that arraylist. I strongly disagree with this scenario being "even worse". It is actually much better, with just a small thing to resolve. – Marko Topolnik Jul 31 '15 at 12:58
  • @MarkoTopolnik: I think we'll have to agree to disagree on this, but I'll clarify my comment. – Jon Skeet Jul 31 '15 at 13:03
  • My guess is that this is not an actual disagreement, but a difference in the extrapolation to what the rest of the code looks like. I may be too optimistic in my version :) – Marko Topolnik Jul 31 '15 at 13:07
3

k++ will return the value of k then increment it.

++k will increment k then return the incremented value.

You should use ++k in your situation.

dotvav
  • 2,808
  • 15
  • 31
2

It works fine, just k++ does first return k and then increment it by one, so you get k, k, k+1, k+2, etc. Use ++k instead. Or use k++ in the first call, too, your choice.

Florian Schaetz
  • 10,454
  • 5
  • 32
  • 58
2

Although your approach works fine with some tweaking of ++ position, with 100 fields you may be better off with reflection. Put field names into an array or a list, then go through them one by one in a loop, and set values based on a loop variable:

String[] fieldNames = new String[] {"memory_version", " mains_voltage_min", ...};
...
Class<MyClass> c = MyClass.class;
for (int i = 0 ; i != fieldNames.length ; i++) {
    Field f = c.getDeclaredField(fieldNames[i]);
    f.setLong(this, array_list_data.get(i));
}

This reduces your list processing code to a few simple lines, and lets you change the order of fields in array_list_data simply by arranging your fieldNames array in proper order.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Just rearranging the statements gives the same effect---that's another advantage of using the increment operator. – Marko Topolnik Jul 31 '15 at 12:48
  • @dasblinkenlight can you please provide an example of the `Class`? – Machado Aug 26 '15 at 13:53
  • 1
    @Holmes Replace `MyClass` with the name of your actual class that holds properties `memory_version`, `mains_voltage_min`, etc. `java.lang.Class` is generic on the class that it represents, so the name of your class needs to come in angular brackets. – Sergey Kalinichenko Aug 26 '15 at 14:15
1

To manage scalability, I'd use an enum and a Map:

enum Var {
    MEMORY_VERSION(0),
    MAINS_VOLTAGE_MIN(1),
    MAINS_VOLTAGE_MAX(2);

    private Integer value;
    Var(Integer value) {
        this.value = value;
    }

    public Integer value() { return value; }
}

List<Long> array_list_data= new ArrayList<>();
Map<Integer, Long> variables = new HashMap<>();

public void getData() {

    for (int j=0; j<array_list_data.size(); j++) {
        variables.put(j, array_list_data.get(j));
    }

}

public void test() {

    System.out.println("Memory version: " + variables.get(Var.MEMORY_VERSION.value()));
}

so that you can add as many vars as you need, and you can retrieve with a meaningful name, like in the test() method.

Andrea Iacono
  • 772
  • 7
  • 20
1

You don't need to maintain the index variable at all; this is why we have iterators:

final Iterator<Integer> iterator = array_list_data.iterator();
memory_version = iterator.next();
mains_voltage_min = iterator.next();
mains_voltage_max = iterator.next();
Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
0

Just about the incrementing part, try this:

public void getData() {
    int i = 0;        
    // get element 0, then increment i
    memory_version = array_list_data.get(i++);
    // get element 1, then increment i
    mains_voltage_min = array_list_data.get(i++);
    // get element 2, then increment i
    mains_voltage_max = array_list_data.get(i++);
}

That's how I do it for example when working with JDBC ResultSet.

Adriaan Koster
  • 15,870
  • 5
  • 45
  • 60