4

I'm currently moving from C++ to Java for work and am having difficulty without const and pointers to make sure intent is always clear. One of the largest problems I'm having is with returning a modified object of the same type.

Take for example a filter function. It's used to filter out values.

public List<int> filter(List<Integer> values) { ... } 

Here everything is Serializable so we could copy the whole list first then modify the contents and return it. Seems a little pointlessly inefficient though. Especially if that list is large. Also copying your inputs every time looks quite clumsy.

We could pass it in normally, modify it and make it clear that we are doing that from the name:

public void modifyInputListWithFilter(List<Integer> values) { ... } 

This is the cleanest approach I can think of - you can copy it before hand if you need to, otherwise just pass it in. However I would still rather not modify input parameters.

We could make the List a member variable of the class we are in and add the filter method to the current class. Chances are though that now our class is doing more than one thing.

We could consider moving the List to it's own class which filter is a function of. It seems a little excessive for one variable though, we'll quickly have more classes than we can keep a track of. Also if we only use this strategy and more than just filtering happens to the List class will unavoidably start doing more than one thing.

So what is the best way of writing this and why?

8
  • 2
    However I would still rather not modify input parameters: why, since the whole point of the method is to modify the list? See Collections.sort(List): it takes a list as argument, and returns void. Commented May 11, 2015 at 13:42
  • 2
    List<int> is not possible in Java. You can't have a List of primitives. Commented May 11, 2015 at 13:43
  • 1
    I think it is ok in Java to modify input parameters. Objects are passed via pointers under the hood exactly for that reason (or that is one of the reasons, at least). Commented May 11, 2015 at 13:44
  • 1
    I agree with @JBNizet, just make sure your method's Javadoc makes it clear what it does. Commented May 11, 2015 at 13:44
  • 1
    FWIW, for a method called filter that accepts a List, I'd expect to be getting a new list with matching items as a return value. (If the items were objects, I'd expect the same references on both lists, not a deep copy.) Same for map and other similar functions. Commented May 11, 2015 at 13:47

1 Answer 1

1

The short answer is that there is not a single best way. Different scenarios will call for different approaches. Different design patterns will call for different approaches.

You've suggested two approaches, and either one of them might be valid depending on the scenario.

I will say that there is nothing inherently wrong with modifying a List that you pass into a function: take a look at the Collections.sort() function, for example. There is also nothing wrong with returning a copy of the List instead.

The only "rule" here is a Liskov rule (not the Liskov rule): your function should do whatever its documentation says it will do. If you're going to modify the List, make sure your documentation says so. If you aren't, make sure it says that instead.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.