I know that more-dynamic-than-Java languages, like Python and Ruby, often allow you to place objects of mixed types in arrays, like so:
["hello", 120, ["world"]]
What I don't understand is why you would ever use a feature like this. If I want to store heterogenous data in Java, I'll usually create an object for it.
For example, say a User has int ID and String name. While I see that in Python/Ruby/PHP you could do something like this:
[["John Smith", 000], ["Smith John", 001], ...]
this seems a bit less safe/OO than creating a class User with attributes ID and name and then having your array:
[<User: name="John Smith", id=000>, <User: name="Smith John", id=001>, ...]
where those <User ...> things represent User objects.
Is there reason to use the former over the latter in languages that support it? Or is there some bigger reason to use heterogenous arrays?
N.B. I am not talking about arrays that include different objects that all implement the same interface or inherit from the same parent, e.g.:
class Square extends Shape
class Triangle extends Shape
[new Square(), new Triangle()]
because that is, to the programmer at least, still a homogenous array as you'll be doing the same thing with each shape (e.g., calling the draw() method), only the methods commonly defined between the two.
As katrielalex wrote: There is no reason not to support heterogeneous lists. In fact, disallowing it would require static typing, and we're back to that old debate. But let's refrain from doing so and instead answer the "why would you use that" part...
To be honest, it is not used that much -- if we make use of the exception in your last paragraph and choose a more liberal definition of "implement the same interface" than e.g. Java or C#. Nearly all of my iterable-crunching code expects all items to implement some interface. Of course it does, otheriwise it could do very little to it!
Don't get me wrong, there are absolutely valid use cases - there's rarely a good reason to write a whole class for containing some data (and even if you add some callables, functional programming sometimes comes to the rescue). A dict would be a more common choice though, and namedtuple is very neat as well. But they are less common than you seem to think, and they are used with thought and discipline, not for cowboy coding.
(Also, you "User as nested list" example is not a good one - since the inner lists are fixed-sized, you better use tuples and that makes it valid even in Haskell (type would be [(String, Integer)]))
Applying a multimethod to the array might make some sense. You switch the strategy to a more functional style in which you focus on a discrete piece of logic (i.e. the multimethod) instead of a discrete piece of data (i.e. the array objects).
In your shapes example, this prevents you from having to define and implement the Shape interface. (Yes, it's not a big deal here, but what if shape was one of several superclasses you wanted to extend? In Java, you're SOL at this point.) Instead, you implement a smart draw() multimethod that first examines the argument and then dispatches to the proper drawing functionality or error handling if the object isn't drawable.
Comparisons between functional and object-oriented styles are all over the place; here are a couple relevant questions that should provide a good start: Functional programming vs Object Oriented programming and Explaining functional programming to object-oriented programmers and less technical people.
Is there reason to use the former over
the latter in languages that support
it?
Yes, there is a very simple reason why you can do this in Python (and i assume the same reason in Ruby):
How would you check that a list is heterogenous?
It can't just compare the types directly because Python has duck typing.
If all the object have some common typeclass Python has no way to guess that either. Everything supports being represented anyways, so you should be able to put them in a list together too.
It wouldn't make any sense to turn lists into the only type that needs a type declaration either.
There is simply no way to prevent you from creating a heterogenous list!
Or is there some bigger reason to use
heterogenous arrays?
No, I can't think of any. As you already mentioned in your question, if you use a heterogenous arrays you're just making things harder than they have to be.
There is no reason not to support heterogeneous lists. It's a limitation for technical reasons, and we don't like those.
Not everything needs to be a class!
In Python, a class is basically a souped up dictionary with some extra stuff anyway. So making a class User is not necessarily any clearer than a dictionary {"name": ..., "id": ...}.
There is nothing to stop you having a heterogeneous array in Java. It is considered poor programming style and using proper POJOs will be faster/more efficient than heterogeneous arrays in Java or any other language as the types of the "fields" are statically known and primitives can be used.
In Java you can
Object[][] array = {{"John Smith", 000}, {"Smith John", 001}, ...};
Eterogenous lists are very useful. For instance, to make the game of snake, I can have a list of blocks like this:
[[x, y, 'down'], [x1, y1, 'down']]
instead of a class for the blocks, and I can access faster to every element.
In Lua an object and an array are the same thing so the reason is more clear. Let's say that Lua takes the weak typing to the extreme
Apart from that, I had a Google Map object and I needed to delete all markers created so far in that map. So I ended up creating an array for markers, an array for circles and an array for places. Then I made a function to iterate over those three arrays and call .remove() on each of them. I then realized that I could just have a single non homogeneous array and insert into them all the objects and iterate once over that array
Here is a simple answer:
N.B. I am not talking about arrays that include different objects that
all implement the same interface or inherit from the same parent, e.g.:
Everything extends java.lang.Object... and that's plenty. There is no reason not to have Object[] and put anything you like in. Object[] are exceptionally useful in any middleware like persistence layer.
Related
Union in thrift, by definition,
provide a means to transport exactly one field of a possible set of
fields, just like union {} in C++. Consequently, union members are
implicitly considered optional (see requiredness).
My reasoning is that Union type does not exist anywhere except C++. Every time when I’m using this contract in Java, I need to split this collection in two, do some separate processing and merge two lists back again.
The only usage of this type is for the single object when you trying to access some field, and if it wasn't set you taking the other one.
Is there any situation, where you should use collection of union objects instead of two separate collections?
Don't try to translate C++ to Java. It's much stronger and translation is impossible in most of the cases. Current Java-like languages are made like memory don't exist. The reason is simplicity. Is much easier to learn such language. That's the reason they don't have unions. In Pascal there are unions too. Old languages don't pretend memory doesn't exist.
There are many use cases for using lists of unions. For example if you need to pass arguments to external function, you may create a Variant type, based on union and wrap the calls with multiple functions with const Variant & arguments.
In Java, to reverse elements in a List, I need to use:
Collections.reverse(list)
I was just wondering why Java doesn't implement the reverse method within the List interface so that I could do the in-place reverse like this:
list.reverse()
Does anyone have any ideas about this?
Why is there no List.reverse() method in Java?
Because there is a Collections.reverse(List) method instead.
Because the API designers figured it was a bad idea to force every List implementation1 to implement a method that wasn't used 99.9% of the time2. This could be addressed by making the method "optional", but that has downsides too; e.g. runtime exceptions.
Because for some kinds of list (stream wrappers / adapters for example) implementing in-place reverse would be problematic. It changes the memory usage characteristics of the list by requiring it to be reified.
Also note that the generic implementation (source code) of reverse() that is provided by Collection uses set to swap elements. It is close to optimal for the standard list types.
#shmosel comments:
I assume OP is asking why it wasn't added as a default method, as List.sort() was.
Good point. Possibly the 99.9% argument applies. Bear in mind that this would only help people with a codebase that is built using a Java 8 or later compilers, etc.
1 - This includes implementations in your codebase and 3rd-party libraries.
2 - 86% of statistics are made up for theatrical effect :-)
For the same reason that fill and rotate and shuffle and swap and infinitely more possible list functions aren't declared in the List interface. They're not part of the "list" abstraction; rather, they can be implemented on top of that abstraction.
Once a List implements the methods already in the List interface, a reverse function can be written on top of the List abstraction without any knowledge of a particular List implementation. Therefore, it would be pointless to force every class implementing List to provide a custom implementation of reverse (and fill, rotate, shuffle, swap, etc.).
Note: This question is a very specific case of "Why does the Collections class contain standalone (static) methods, instead of them being added to the List interface?" - one could even consider is as a duplicate. Beyond that, arguing about the reasoning behind the decision for each individual method is reading tea leaves, and nobody can tell "the reason" for the design decision for the particular case of the reverse method (until, maybe Josh Bloch posts an answer here). Interestingly, this is a point that is not covered in the Java Collections API Design FAQ...
Some of the other answers seem convincing at the first glance, but raise other questions. Particularly, some of them don't give a reason for the design decision at all. Even if there are other ways to emulate the behavior of a certain method, or when a method is not used "99.9% of all time", it can still make sense to include it in the interface.
Looking at the List interface, you will notice that you can basically implement all methods based on two others:
T get(int index)
int size()
(For a mutable list, you also need set). These are exactly the ones that are still abstract in AbstractList. So all other methods are rather "convenience" methods that can be implemented canonically, based on these two methods. In this regard, I think that the answer Sam Estep contains an important point: One could argue to implement dozens of other methods. And there would certainly be good reasons to do so. Having a look at the actual implementation of Collections#reverse(List):
public static void reverse(List<?> list) {
int size = list.size();
if (size < REVERSE_THRESHOLD || list instanceof RandomAccess) {
for (int i=0, mid=size>>1, j=size-1; i<mid; i++, j--)
swap(list, i, j);
} else {
ListIterator fwd = list.listIterator();
ListIterator rev = list.listIterator(size);
for (int i=0, mid=list.size()>>1; i<mid; i++) {
Object tmp = fwd.next();
fwd.set(rev.previous());
rev.set(tmp);
}
}
}
What is this REVERSE_THRESHOLD and RandomAccess thing there? Seriously, if I felt the necessity to introduce a tagging interface like RandomAccess, I would strongly question my design. Whenever you have a method like
void doSomethingWith(Type x) {
if (x instanceof Special) doSomethingSpecial((Special)x);
else doSomethingNormal(x);
}
then this is a strong sign that this should actually be a polymorphic method, which should be implemented accordingly for the Special type.
So yes, it have been justified to pull the reverse method into the interface, to allow a polymorphic implementation. The same applies to fill rotate, shuffle, swap, sort and others. Similarly, one could have introduced a static method like
Collections.containsAll(containing, others);
that offers what is now done with the Collection#containsAll method. But in general: The designers chose a particular set of methods that they found suitable. One of the reasonings behind leaving out certain methods may be given by one of the bottom lines of the talk about "How to Design a Good API & Why it Matters" by Joshua Bloch, one of the core designers of the Java Collections API:
When in doubt, leave it out
Interestingly, of all the methods for which a polymorphic implementation (via a method in the List interface) could have been reasonable, one actually found its way into the interface, using a Java 8 default method:List#sort(). Maybe others, like reverse, will be added later...
Because Collection is an utilitarian class, that actually based on one of SOLID principle : S - Single Responsibility Principle
This principle states that if we have 2 reasons to change for a class, we have to split the functionality in two classes.
You have a class that play a some role, and if you need to manipulate of inner data you need to create some subsidiary class, that will plays another role.
If you need list.reverse() you need to use Eclipse Collections, when you can use just list.reverseThis(), see this. In JDK list, a lot of method (like sort, max, min) does not be added.
It's two different ways of API design:
A lot of method in Collection -> rich collection -> Eclipse
Collections, drawback: a lot of rarely used method in List,
Only most used method and Utility class -> JDK
collection, drawback: need to use Utility class like Collections,
Reverse is defined in Collections (with an extra (s)). This is not a part of collection hierarchy, rather it has been given as a part of utility class which can be used for different Lists.
Reversing a list is not a key part of defining a list , so its kept out of interface and given separately. If defined in the interface, everyone will have to implement it, which may not be suitable for all.
The makers of collection could have build this in List hierarchy as well, ( Since most list derivations have an abstract class in between, they could have put it in any abstract class in between). However, to simplify everyone's life it makes sense to keep it in single utility class so that we don't have to figure out which class to look for all collection related utility functions.
I'm rather fresh in programming and I try to make simple app. App will allow user to make a character sheet for popular RPG game. Right now I trying to model it (on paper) and have (maybe a stupid one) question.
Each character have set of skills - a lot (33). And each skill cane have value of 0-5. Now my question is: is it better to make 33 ints insied Character object or make Class Skill and make array of Skills in Character? My knowledge of Java is not good enough to decide :( If anyone find some useful article about it or can just simply explain it to me I would be grateful.
I just hope it is not completely stupid question :)
Have a nice day!
If you have a fixed number of skills you can use multiple attributes, will increase readability when used, but will make your class a bit ugly and less mantainable.
If values are always an int, I would reccomend to use a Map instead of array or Collection.
Map<String, Integer> skills;
So you can have a class with nice declaration and refer to skills by name and not by position in the array:
Integer strenghtLevel = skills.get("strenght");
I definitely recommend to create a specific Skill class. Today you are using ints from 0 to 5; but such things tend to become more complex pretty fast.
Therefore you should carefully design the "Skill" class upfront (you might also consider to have a Skill interface; as you might face the need to have different implementations (for different skill types) at some future point).
You character class could then be using a dynamic container; for example java.util.ArrayList to hold all the various skills.
It's probably better to make a class skill, because then you can ensure each skill has a name and a value. Then, you can also do things like creating a method to print out or display the name and value, and if you want to add another attribute to the skill, it is fairly easy.
You could use an array of int elements. It should be enough, unless you want some custom logic. If the values should have states and actions, then they should be objects.
Say, for example, I want to make a cash register program. Ignoring, for the sake of being compact, that one wouldn't use floats for currency my first instinct is to use an enum for the denominations, something along the lines of :
private enum Currency {
ONE_HUNDRED(100.00f),
FIFTY( 50.00f),
TWENTY( 20.00f),
TEN( 10.00f),
FIVE( 5.00f),
TWO( 2.00f),
ONE( 1.00f),
HALF_DOLLAR( 0.50f),
QUARTER( 0.25f),
DIME( 0.10f),
NICKEL( 0.05f),
PENNY( 0.01f);
private final float value;
Currency(float value) {
this.value = value;
}
public float getValue() {
return this.value;
}
#Override
public String toString() {
return this.name().replace("_", " ");
}
}
But last I followed instinct, sans forethought, and did something similar for a Morse Code Converter, someone suggested that I use a map instead, explicitly a Bimap. I see the appeal of that collection in that particular scenario, but generally speaking I wanted to inquire if there were any reason to prefer one when the other could be used? If instead of the above code I did this:
Map<String, Float> currency = new LinkedHashMap<>();
currency.put("One Hundred", 100.00f);
currency.put("Fifty", 50.00f);
currency.put("Twenty", 20.00f);
currency.put("Ten", 10.00f);
currency.put("Five", 5.00f);
currency.put("Two", 2.00f);
currency.put("One", 1.00f);
currency.put("Half Dollar", 0.50f);
currency.put("Quarter", 0.25f);
currency.put("Dime", 0.10f);
currency.put("Nickel", 0.05f);
currency.put("Penny", 0.01f);
Would it be superior for any reason?
In cases like these were either could be utilized, are there any performance advantages to using one over another? Is one more preferable/conventional? More maintainable/adaptable?
Is there any rule of thumb I could use for when I should use one over the other?
Here are things I like to keep in mind:
Enums are best used (and in the languages I know of, may only be used) to define a known set of items ahead of time. This has a nice benefit of treating what really boils down to frequently used "data" as code in a very readable way.
In my opinion, any code that relies on frequently hardcoded strings, like you would need to use if implementing data like that in a map is more difficult to read and maintain. This leads to "magic strings", which is a no-no when avoidable.
It's not immediately clear what should exist in the map until you go check, and it's not clear if it's potentially being modified elsewhere. Consider, that if you got an enum value wrong, the code will not even compile. Get a string key wrong, and you might not notice until much later.
Regarding performance, I doubt there is a large difference between the two. Enums are treated largely the same as objects, I suppose the benefit comes from accessing the data as a field on the object rather than a hash lookup.
This article doesn't go in depth as I would like, but may be a good starting point: Memory Consumption of Java Data Types
It is quite common practice to use an enum as keys for a known map and that offers another way of associating data with a set of specific items (rather than setting them as fields on the enum). I believe this approach would be my preferred method since setting lots of fields on an enum makes them feel too much like a class rather than a method of referencing. This doesn't have the same problems as a normal map because since the keys must be enums you don't need to worry about any other keys "accidentally" being added to the map. It seems Java as a whole supports this approach as they provide the EnumMap class.
I would say that the main difference between your two pieces of code is that in case of enum you have fixed list of denominations which are "type-safe". While operating with strings and maps it is very easy to misspell some string, introducing bugs that are hard to spot.
I would use enum in this case it is more sensible and if this were something that were to be used by other people enum's have the associated values display for you if you are using pretty much any ide, where as if you are using a map neither the key or the value is readily available to you. There are other reasons but that was one that came to mind.
Would it be superior for any reason?
The Map design would be appropriate for dynamic data, whereas the enum design would be appropriate for fixed data.
In cases like these were either could be utilized, are there any
performance advantages to using one over another?
Insignificant.
Is one more preferable/conventional?
Only when considering the specific problem to be solved.
More maintainable/adaptable?
Again, it depends on the problem you're trying to solve.
Is there any rule of thumb I could use for when I should use one over
the other?
Whether you're working with a limited, non-varying dataset known at compile time.
I am writing a program that will be heavily reliant on ... something ... that stores data like an array where I am able to access any point of the data at any given time as I can in an array.
I know that the java library has an Array class that I could use or I could use a raw array[].
I expect that using the Array type is a bit easier to code, but I expect that it is slightly less efficient as well.
My question is, which is better to use between these two, and is there a better way to accomplish the same result?
Actually Array would be of no help -- it's not what you think it is. The class java.util.ArrayList, on the other hand, is. In general, if you can program with collection classes like ArrayList, do so -- you'll more easily arrive at correct, flexible software that's easier to read, too. And that "if" applies almost all the time; raw arrays are something you use as a last resort or, more often, when a method you want to call requires one as an argument.
The Array class is used for Java reflection and is very, very, rarely used.
If you want to store data in an array, use plain old arrays, indicated with [], or as Gabe's comment on the question suggests, java.util.ArrayList. ArrayList is, as your comment suggests easier to code (when it comes to adding and removing elements!!) but yes, is slightly less efficient. For variable-size collections, ArrayList is all but required.
My question is, which is better to use between these two, and is there a better way to accomplish the same result?
It depends on what you are trying to achieve:
If the number of elements in the array is known ahead of time, then an array type is a good fit. If not, a List type is (at least) more convenient to use.
The List interface offers a number of methods such as contains, insert, remove and so on that can save you coding ... if you need to do that sort of thing.
If properly used, an array type will use less space. The difference is particularly significant for arrays of primitive types where using a List means that the elements need to be represented using wrapper types (e.g. byte becomes Byte).
The Array class is not useful in this context, and neither is the Arrays class. The choice is between ArrayList (or some other List implementation class) and primitive arrays.
In terms of ease of use, the Array class is a lot easier to code.
The array[] is quite a problem in terms of the case that you need to know
the size of the list of objects beforehand.
Instead, you could use a HashMap. It is very efficient in search as well as sorting as
the entire process is carried out in terms of key values.
You could declare a HashMap as:
HashMap<String, Object> map = new HashMap<String, Object>();
For the Object you can use your class, and for key use the value which needs to be unique.