Given an IP Address Range ( a.b.c.d - a.b.c.e) i would like a method to return the ip address's in an array list between the range.
Option 1 :
public static int getIPAddressesFromRange(String rangeStr, List list ) ;
return value is count and the input list would be populated with list of IP's the range has
Option 2:
public static List getIPAddressesFromRange(String rangeStr)
return value is the list of ip addresses'
My Option is 2, but that is intuition, not able to support my argument though.
Edit: Is there any design principle the option 1 is violation ?
I'd say
public static List<String> getIPAddressesFromRange(String rangeStr)
if you decide to represent IP addresses as strings.
Arguments against #1:
The caller needs to construct the list in advance
It is not straightforward what the return value is unless you document it
The method mutates one of its arguments, which is not in general forbidden, but it is best to avoid surprising the user of your API (especially if they are prone not to read the documentation)
Passing in a null value accidentally for the list parameter will result in a NullPointerException.
You can always get the length of the list from the list itself if you really care about it.
Prefer the option 2 to the option 1.
The list contains its count anyway, so there is no need to return two values (the count and the list).
Also, since you know the type of the list, you can use generics: List<String>.
Finally, you might also consider taking two arguments: the beginning and the end of the range.
Why do you want to return count in first method? You can fetch the number of IP's from List itself.
Second method should be the preferred one
Your second option is best because the first option has two problems:
It's redundant. If a List is returned, you can use its size() method to get that count, so you gain nothing by returning the count.
The list must be validated and in some cases the method outright cannot perform its work. If the caller passes null, there is danger of a NullPointerException being thrown if the code was not written carefully. Also in that case, reassigning the parameter to point to a new list will not be observed by the caller, so your only remotely sane option is to throw a clear exception. With the second option, you have full control of the list until it is returned to the caller.
Option two is probably better, since it is clear for any reader what is the method returning.
Method 1 might cause future coders to spend time thinking what is this parameter (unless it is properly documented), while method 2 is realy straight forward.
Option two also makes it more neat if you later need to iterate on the retrieved list, no need for temporary variables:
for (Object o : getIPAddressesFromRange(String rangeStr)) { ... }
You should also prefer using the generic type List<> and not the raw type.
Stuff in, stuff out. That's what your Option 2 does.
Option 1 mutates its input argument and returns redundant value (count, which can be got from the list).
Another thing is, perhaps a range of IP addresses would be described better by some other type than a String.
IMO method signature suggests it will return a list of ip addresses from range, not how many addresses are in this range, hence I'm also for option 2.
I think the 2nd one is better :
The count is the size of the list
You don't have to give a list to the function
Less null pointer exception risk
Your intuition is mine also, it is better to let getIPAddressesFromRange use its preferred implementation of List and avoid someone to give you an already populated list.
My opinion is that the second method signature is generally the best one as the first one will exposes your list object to concurrent modification. Thus, at the end of your method, it may hold less, more, other objects than expected.
It depends on whether you want to fill pre-created lists, or create new ones.
For example: You could do multiple calls to your function using the same List object to save some memory.
Or: To compare multiple lists, you may want to return a new List for each call.
I would go with Option 2.
Related
I am just curious about the Lists class implementation of google guava, we have two methods to create List from Array,
Lists.asList(E first, E[] rest)
Lists.asList(E first, E second, E[] rest)
Why do these methods has first and rest separately? cant it be like Arrays.asList implementation of java ?
The only thing I am able to see is the first and second is nullable and rest is not nullable
Can anyone help to understand this ?
Ok, so the job of the Lists.asList() is not exactly to directly convert an array to a list.
Suppose we have an array, and we want to insert an element to it, we can’t do it as the array size is fixed. One solution to this problem is to allocate an new array of +1 the size of the original array and copy all elements from the original array to the new array. This works but it is highly inefficient.
Guava provides an efficent solution to this problem – Guava’s Lists.asList() method returns an unmodifiable list backed by the original array which also contains the specified element.
source: https://www.techiedelight.com/guava-lists-class-java/
So basically, you can use it to just convert an array by giving the first and/or second parameters (depending upon what method you are using) as null, and giving the "rest" parameter as your array.
This will return your array as list, perhaps with null as the first index (and second as well, depending on what you are using)
But if you want, you can use the same methods to get a list with some specific data appended to your array (at first and second index values)
Hope this was helpful!
The main reason these methods exist is to help you when you write a method with a signature like
void foo(Bar first, Bar... rest);
which is something you'd do when you want to allow the user to call the method as if it were a method with just a varargs parameter, but you want to require that it be called with a minimum of one or two arguments (whereas varargs alone would allow them to call it with zero). In the implementation of such a method, you might want to treat those arguments as a single list. Lists.asList does that without doing any array copying:
void foo(Bar first, Bar... rest) {
List<Bar> bars = Lists.asList(first, rest);
// ...
}
I have a very simple question that I would like to ask. There are 2 ways by which you initialize a variable :
1.
List<SalesReturnJson> salesReturnJsons=new LinkedList<>();
salesReturnJsons=salesRepository.findSales();
2.
List<SalesReturnJson> salesReturnJsons=salesRepository.findSales();
So in this 2 scenerios how is the memory allocated and In the second scenerio which implementation(LinkedList or ArrayList) of List is called.
Any help will be highly appreciated.
If in the first scenario the second line is exactly below the first line, the "new" statement would have no effect. You create an empty LinkedList, put a reference on it, then you change the reference to point to another List (I suppose findSales returns a List) and finally the garbage collector of java will erase the empty LinkedList, since there is no reference to it anymore.
In the second scenario you return a List (as I suppose) and put a reference to this List.
In both cases an object returned by salesRepository.findSales() will be assigned to your variable. Since the implementation is the same in both cases, without knowing the actual implementation we can only say that the object will be of the same class in both cases, however, creating an object and then re-assigning the variable to another reference as in your first example makes little sense. The second will achieve the same result, but with reduced effort.
Both scenarios end up with exactly the same List in your salesReturnJsons variable, with the List type being the one returned by salesRepository.findSales(). From the code given, we can't tell what type is actually returned from this method.
The only difference is, the first scenario creates an absolutely unnecessary empty LinkedList, stores it into your salesReturnJsons variable, and immediately replaces it by the list from salesRepository.findSales(), making the LinkedList garbage. So, please use the second version.
If (for whatever special reason) your intent might be to have a LinkedList of the salesRepository.findSales() results, then you could do:
List<SalesReturnJson> salesReturnJsons=
new LinkedList<SalesReturnJson>(salesRepository.findSales());
That will copy the elements from the method result into a fresh LinkedList, then you are sure about the List type.
But the typical code snippet would be your version 2.
For example, I would like to do something like the following in java:
int[] numbers = {1,2,3,4,5};
int[] result = numbers*2;
//result now equals {2,4,6,8,10};
Is this possible to do without iterating through the array? Would I need to use a different data type, such as ArrayList? The current iterating step is taking up some time, and I'm hoping something like this would help.
No, you can't multiply each item in an array without iterating through the entire array. As pointed out in the comments, even if you could use the * operator in such a way the implementation would still have to touch each item in the array.
Further, a different data type would have to do the same thing.
I think a different answer from the obvious may be beneficial to others who have the same problem and don't mind a layer of complexity (or two).
In Haskell, there is something known as "Lazy Evaluation", where you could do something like multiply an infinitely large array by two, and Haskell would "do" that. When you accessed the array, it would try to evaluate everything as needed. In Java, we have no such luxury, but we can emulate this behavior in a controllable manner.
You will need to create or extend your own List class and add some new functions. You would need functions for each mathematical operation you wanted to support. I have examples below.
LazyList ll = new LazyList();
// Add a couple million objects
ll.multiplyList(2);
The internal implementation of this would be to create a Queue that stores all the primitive operations you need to perform, so that order of operations is preserved. Now, each time an element is read, you perform all operations in the Queue before returning the result. This means that reads are very slow (depending on the number of operations performed), but we at least get the desired result.
If you find yourself iterating through the whole array each time, it may be useful to de-queue at the end instead of preserving the original values.
If you find that you are making random accesses, I would preserve the original values and returned modified results when called.
If you need to update entries, you will need to decide what that means. Are you replacing a value there, or are you replacing a value after the operations were performed? Depending on your answer, you may need to run backwards through the queue to get a "pre-operations" value to replace an older value. The reasoning is that on the next read of that same object, the operations would be applied again and then the value would be restored to what you intended to replace in the list.
There may be other nuances with this solution, and again the way you implement it would be entirely different depending on your needs and how you access this (sequentially or randomly), but it should be a good start.
With the introduction of Java 8 this task can be done using streams.
private long tileSize(int[] sizes) {
return IntStream.of(sizes).reduce(1, (x, y) -> x * y);
}
No it isn't. If your collection is really big and you want to do it faster you can try to operates on elements in 2 or more threads, but you have to take care of synchronization(use synchronized collection) or divide your collection to 2(or more) collections and in each thread operate on one collection. I'm not sure wheather it will be faster than just iterating through the array - it depends on size of your collection and on what you want to do with each element. If you want to use this solution you will have wheather is it faster in your case - it might be slower and definitely it will be much more complicated.
Generally - if it's not critical part of code and time of execution isn't too long i would leave it as it is now.
There's no doubt that in-out parameters leads to confused code since they may increase unexpected/unpredictabled side-effects.
So, many good programmers say :
Avoid in-out parameters for changing mutable method parameters. Prefer to keep parameters unchanged.
For a perfectionist programmer who expects his code to be the most clean and understandable, does this "rule" must be applied in all case ?
For instance, suppose a basic method for adding elements to a simple list, there's two ways :
First way (with in-out parameter):
private void addElementsToExistingList(List<String> myList){
myList.add("Foo");
myList.add("Bar");
}
and the caller being :
List<String> myList = new ArrayList<String>();
//.......Several Instructions (or not) .....
addElementsToExistingList(myList);
Second way without out parameter :
private List<String> addElementsToExistingList(List<String> originalList){
List<String> filledList = new ArrayList<String>(originalList); //add existing elements
filledList.add("Foo");
filledList.add("Bar");
return filledList;
}
and the caller being :
List<String> myList = new ArrayList<String>();
//.......Several Instructions (or not) .....
myList.addAll(addElementsToExistingList(myList));
Pros of second way :
Parameter are not modified => no risk of unexpected side-effects for a new code reader.
Cons of second way :
Very verbose and very less readable ...
Of course, you would tell me that for a code as simple as this one, first way is really more convenient.
But, if we don't consider the difficulty of any concept/code, I juge the second way more logical and obvious for any readers (beginners or not).
However, it violates the CQS principle that consider "command" methods having void return with potential (but allowed since it's the convention) side-effects and "query" methods having a return type and without side-effects.
So, what should a motivate programmer adopt ? Mix of two accorging to the code case ? Or keep the "law" expecting to always avoid in-out parameters...
(Of course, method for adding Element is named for expliciting the example, and would be a bad name choice in real code).
I think the law should be:
Use what is more straight-forward, but always, always document the behavior of your methods extensively.
Your second example is a very nice case where without documentation you would have a guaranteed bug: the name of the method is addElementsToExistingList, but the method does not add elements to the existing list - it creates a new one. A counter-intuitive and misleading name, to say the least...
There is a third way. Wrap List<String> into a class that knows how to add elements to itself:
class ElementList {
private List<String> = new ArrayList<String>();
public void addElements(Element... elements);
}
I like this approach because it keeps the List implementation private. You don't have to worry if someone passes an immutable list to your method or whether parameters are modified. The code is simpler. Long method names like addElementsToExistingList are code smells that an object is trying to do something another object should be doing.
You should always document when mutating an object that is a parameter because otherwise this can have unintended side effects for the caller. In the first case I agree with the others that have commented that the method name is sufficient documentation.
In your second example, the elements that are already present in myList seem to be added twice. In fact you could entirely remove the parameter of the addElementsToExistingList method and rewrite it as:
private List<String> getElements() {
List<String> filledList = new ArrayList<String>();
filledList.add("Foo");
filledList.add("Bar");
return filledList;
}
List<String> myList = new ArrayList<String>();
//.......Several Instructions (or not) .....
myList.addAll(getElements());
Note that this code is not equivalent to your second example because the elements are only added once, but I think this is actually what you intended. This is the style that I usually prefer. This code is easier to understand and more flexible than the first example without adding extra code (it may degrade performance very slightly but this usually isn't a concern). The client of getElements() can now also do other things with the element list besides adding it to an existing collection.
It's fine to change/mutate parameters as long as it's documented. And of course with a method name of "addElementsToExistingList", what else should someone expect? However, as someone previously pointed out, your second implementation returns a copy and doesn't modify the original, so the method name is now misleading. Your first way is a perfectly acceptable way of doing things. The only other additional improvements is to possibly add a true/false value to the return indicating true if only all the elements were added to the list.
In the case of your example the name makes it clear - "addElementsToExistingList" to me seems pretty clearly to hint that you're going to .. er.. you know. But your concern would be justified with a less obvious name.
For example, in ruby this is commonly handled with naming conventions
"a".upcase => gives you the uppercase of the variable, leaves the original unchanged
"a".upcase! => alters the original variable
If fooService.getFoos() returns List<Foo>.
then you can write this:
List<Foo> fooList = fooService.getFoos();
or this:
List<Foo> fooList = new ArrayList(fooService.getFoos());
Is there any significant difference in the resulting fooList between these two approaches?
Yes - you are creating a completely new List, containing the elements of the original one. You are duplicating the collection in memory, and iterating it from start to end. You are also not using instance provided by the service, and you can't modify the original. And finally, you've omitted the generics declaration in the 2nd snippet.
So use the first option.
Update: you indicated you are not allowed to modify the original list. This is actually a problem of fooService, not of its clients. If the service is also in your control, return Collections.unmodifiableList(originalList) - thus clients won't be able to perform modification operations (on attempt an exception will be thrown)
The second isn't really a good idea because you omit the generic part.
But the main problem is the unnecessary code which will be called. You can look at the ArrayList code source, and you'll see all the operations used in the constructor. If you only need a List, and fooService.getFoos() returns a valid List, you should stick with it.
The result of those two statement will be more or less the same unless:
later you check if your list is an instance of ArrayList and cast it, but let's face it, you would have declared ArrayList<Foo> if it was the case.
the list returned by fooService.getFoos() shouldn't be modified (for any reason) but you still want modify elements in the List on your side (without affecting the original list).
Resources :
grepcode - ArrayList
I'd stick with the first one just because it reads lots easier and makes much more sense than the second one.
In the second statement it returns only of List type. If you are sure of method returning of same type den you can use firs type.