I know that if you have a loop that modifies the count of the items in the loop, using the NSEnumerator on a set is the best way to make sure your code blows up, however I would like to understand the performance tradeoffs between the NSEnumerator class and just an old school for loop
Using the new for (... in ...) syntax in Objective-C 2.0 is generally the fastest way to iterate over a collection because it can maintain a buffer on the stack and get batches of items into it.
Using NSEnumerator is generally the slowest way because it often copies the collection being iterated; for immutable collections this can be cheap (equivalent to -retain) but for mutable collections it can cause an immutable copy to be created.
Doing your own iteration — for example, using -[NSArray objectAtIndex:] — will generally fall somewhere in between because while you won't have the potential copying overhead, you also won't be getting batches of objects from the underlying collection.
(PS - This question should be tagged as Objective-C, not C, since NSEnumerator is a Cocoa class and the new for (... in ...) syntax is specific to Objective-C.)
After running the test several times, the result is almost the same. Each measure block runs 10 times consecutively.
The result in my case from the fastest to the slowest:
For..in (testPerformanceExample3) (0.006 sec)
While (testPerformanceExample4) (0.026 sec)
For(;;) (testPerformanceExample1) (0.027 sec)
Enumeration block (testPerformanceExample2) (0.067 sec)
The for and while loop is almost the same.
The tmp is an NSArray which contains 1 million objects from 0 to 999999.
- (NSArray *)createArray
{
self.tmpArray = [NSMutableArray array];
for (int i = 0; i < 1000000; i++)
{
[self.tmpArray addObject:#(i)];
}
return self.tmpArray;
}
The whole code:
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (strong, nonatomic) NSMutableArray *tmpArray;
- (NSArray *)createArray;
#end
ViewController.m
#import "ViewController.h"
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self createArray];
}
- (NSArray *)createArray
{
self.tmpArray = [NSMutableArray array];
for (int i = 0; i < 1000000; i++)
{
[self.tmpArray addObject:#(i)];
}
return self.tmpArray;
}
#end
MyTestfile.m
#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#import "ViewController.h"
#interface TestCaseXcodeTests : XCTestCase
{
ViewController *vc;
NSArray *tmp;
}
#end
#implementation TestCaseXcodeTests
- (void)setUp {
[super setUp];
vc = [[ViewController alloc] init];
tmp = vc.createArray;
}
- (void)testPerformanceExample1
{
[self measureBlock:^{
for (int i = 0; i < [tmp count]; i++)
{
[tmp objectAtIndex:i];
}
}];
}
- (void)testPerformanceExample2
{
[self measureBlock:^{
[tmp enumerateObjectsUsingBlock:^(NSNumber *obj, NSUInteger idx, BOOL *stop) {
obj;
}];
}];
}
- (void)testPerformanceExample3
{
[self measureBlock:^{
for (NSNumber *num in tmp)
{
num;
}
}];
}
- (void)testPerformanceExample4
{
[self measureBlock:^{
int i = 0;
while (i < [tmp count])
{
[tmp objectAtIndex:i];
i++;
}
}];
}
#end
For more information visit: Apples "About Testing with Xcode"
They are very similar. With Objective-C 2.0 most enumerations now default to NSFastEnumeration which creates a buffer of the addresses to each object in the collection that it can then deliver. The one step that you save over the classic for loop is not having to call objectAtIndex:i each time inside the loop. The internals of the collection you are enumerating implement fast enumeration with out calling objectAtIndex:i method.
The buffer is part of the reason that you can't mutate a collection as you enumerate, the address of the objects will change and the buffer that was built will no longer match.
As a bonus the format in 2.0 looks as nice as the classic for loop:
for ( Type newVariable in expression ) {
stmts
}
Read the following documentaion to go deeper:
NSFastEnumeration Protocol Reference
Related
I'm currently working on a project that's split in two classes, the class 'Array' and the class 'PPCalcVals'. Because other classes, that will be added, will also have to have access the array, I thought it would be the best to write the array class, containing an NSMutableArray and Subclass all the others (beginning with the PPCalcVals class.
So the 'PPCalcVals' class needs to access the elements of the array in the superclass 'Array'.
(Please correct me if this is the wrong approach).
As mentioned the whole program is written and well working in C but to create a GUI and eventually an OSX or IOS application I started to learn OOProgramming with Objecitve C.
Anyways, when I reference the objects in the array of the superclass the only value that gets printed is "null" which is not really what I want.
Here is the code:
main routine:
#import <Foundation/Foundation.h>
#import "Array.h"
#import "PPCalcVals.h"
int main(int argc, const char * argv[])
{
#autoreleasepool
{
Array *prices = [[Array alloc]initWithName:#0];
PPCalcVals *myVals = [[PPCalcVals alloc]init];
[prices addValue:#12];
[prices addValue:#13];
[prices addValue:#14];
[prices addValue:#15];
[prices addValue:#15];
[prices print];
[myVals print];
}
return 0;
}
array.h file:
#import <Foundation/Foundation.h>
#interface Array : NSObject
{
NSMutableArray *prices;
}
-(id) initWithName: (NSNumber *) values;
-(void) addValue: (NSNumber *) value;
-(void) print;
-(NSMutableArray *) prices;
#end
array.m
#import "Array.h"
#implementation Array
-(id) initWithName:(NSNumber *)values
{
self = [super init];
if(self)
{
prices = [NSMutableArray array];
}
return self;
}
-(void) addValue: (NSNumber *) value
{
[prices addObject:value];
}
-(void) print
{
NSLog(#"%#",prices);
}
-(NSMutableArray *)prices
{
return prices;
}
#end
PPCalcVals.h:
#import "Array.h"
#interface PPCalcVals : Array
#property id high,low,open,close;
-(void) setHigh:(NSMutableArray *)h setLow:(NSMutableArray *)l; //set high and low
-(void) setOpen:(NSMutableArray *)o setClose:(NSMutableArray *)c; //set open and close
-(void) sort; //sort array
-(void) print; //debugging tool
#end
PPCalcVals.m:
#import "PPCalcVals.h"
#implementation PPCalcVals
#synthesize high,low,open,close;
-(void) setOpen:(NSMutableArray *)o setClose:(NSMutableArray *)c
{
o = prices[0];
c = prices[2];
open = o;
close = c;
}
-(void) sort;
{
[prices sortedArrayUsingComparator:^(NSString *str1, NSString *str2) {
return [str1 compare:str2 options:NSNumericSearch];
}];
}
-(void) setHigh:(NSMutableArray *)h setLow:(NSMutableArray *)
{
h = prices[0];
l = prices[2];
high = h;
low = l;
}
-(void) print
{
NSLog(#"open: %#",open);
NSLog(#"close: %#",close);
NSLog(#"high: %#",high);
NSLog(#"low: %#",low);
}
#end
The running program outputs only:
2013-08-05 10:21:08.546 prog1[1314:303] (
12,
13,
14,
15,
15
)
open: (null)
close: (null)
high: (null)
low: (null)
I realize that this is probably a really basic question but I would appreciate your help a lot and I already thank you if you read until this point ;)
You have created two distinct, completely unrelated objects prices and myVals:
Array *prices = [[Array alloc]initWithName:#0];
PPCalcVals *myVals = [[PPCalcVals alloc]init];
What you probably meant is to create a PPCalcVals object (which inherits
all methods from the superclass Array):
PPCalcVals *prices = [[PPCalcVals alloc]init];
[prices addValue:#12]; // invokes `addValue` method from superclass "Array"
// ...
[prices print]; // invokes `print` method from "PPCalcVals"
You also have to implement init in the PPCalcVals class in such a way
that it calls the "designated initializer" initWithName in the superclass.
I have one question. Where did you make calls for the functions
-(void) setHigh:(NSMutableArray *)h setLow:(NSMutableArray *)l;
-(void) setOpen:(NSMutableArray *)o setClose:(NSMutableArray *)c;
Because all I can see is that these functions are not called. So the properties high, low, open & close are not yet assigned and thus they return Null.
Also may I know the reason why are you overriding the parameters inside above mentioned functions?
o = prices[0];
c = prices[2];
and
h = prices[0];
l = prices[2];
I understand that this topic has been done before but I wanted to bring it up again for a specific reason, I have a function designed to move an item from one array to another, removing the item from the array it was originally in, but whenever I test it, it doesnt seem to work
-(void) moveOpperand: (NSMutableArray *) moveFrom :(NSMutableArray *) moveTo{
NSString *opperandObject = [moveFrom lastObject];
if (opperandObject) {
[moveTo addObject:moveFrom.lastObject];
[moveFrom removeLastObject];
}
}
the method above is called in this method
-(NSMutableArray *) giveHand: (NSMutableArray *) hand : (NSMutableArray *)refrenceDeck{
for (int i=0; i<6; i++) {
[self moveOpperand:refrenceDeck :hand];
}
return hand;
}
the error when testing seems to be located when I try to implement the currentHand method
-(NSMutableArray *) currentHand{
if (_currentHand == nil) {
self.currentHand = [self.myDeck giveHand:self.currentHand :self.myDeck.currentDeck];
}
return _currentHand;
}
If you're trying to do what I think here is a very very simple category that should do it for any object.
NSObject+Move.h
#import <Foundation/Foundation.h>
#interface NSObject (Move)
/*
Returns true if it sucessfully moves the object between arrays.
*/
- (BOOL)moveFromArray:(NSMutableArray *)arrayA toArray:(NSMutableArray *)arrayB;
#end
NSObject+Move.m
#import "NSObject+Move.h"
#implementation NSObject (Move)
- (BOOL)moveFromArray:(NSMutableArray *)arrayA toArray:(NSMutableArray *)arrayB
{
if ([arrayA containsObject:self]) {
[arrayA removeObject:self];
[arrayB addObject:self];
return YES;
} else {
return NO;
}
}
#end
It's possible that you aren't setting the _currentHand variable to nil at the appropriate time, thus you may not have the correct current hand which may make it 'seem' like an issue with your array swapping.
Usually I treat instance variables in Objective-c like this:
#interface MyClass : NSObject
#property (nonatomic, retain) NSMutableArray *mutableArray;
#end
#implementation MyClass
#synthesize mutableArray;
- (id) init {
if((self = [super init])) {
self.mutableArray = [NSMutableArray array];
}
return self;
}
- (void) dealloc {
[mutableArray release];
[super dealloc];
}
#end
I feel pretty comfortable w/ the above syntax. However I'm not so comfortable w/ the syntax for a 2D array instance variable like NSUInteger 2dArray[10][10].
What's the appropriate Objective-c syntax for a 2d array instance variable with regards to interface declaration, synthesizing getters/setters and memory management?
You don't need to allocate memory for your array; they are perfectly fine being defined in the class and they will always exist, at the same size. You therefore don't need to worry about memory management and your getter/setters should be defined manually, depending on what you want to do. For example these getter/setter methods allow getting/setting an individual value:
#interface MyClass : NSObject
{
NSUInteger _twoDeeArray[10][10];
}
- (void)setTwoDeeArrayX:(NSUInteger)x y:(NSUInteger)y value:(NSUInteger)value;
- (NSUInteger)twoDeeArrayX:(NSUInteger)x y:(NSUInteger)y;
#end
#implementation MyClass
- (void)setTwoDeeArrayX:(NSUInteger)x y:(NSUInteger)y value:(NSUInteger)value
{
_twoDeeArray[x][y] = value;
}
- (NSUInteger)twoDeeArrayX:(NSUInteger)x y:(NSUInteger)y
{
return _twoDeeArray[x][y];
}
#end
You should probably have range-checking for x and y, but you get the idea.
That's not an Objective C syntax. It's pure C syntax. You don't need to exclusively say that you want a 2D array of objc objects. Just declare/define the mutable array and add other arrays to it.
For two-demensional arrays, you can:
Go with C arrays (like what you mentioned in the post)
Add NSMutableArray into NSMutableArray
Create a class to implement your version of 2D-array
If you just want to use primitive types in your array, all three are good.
For Objective-C objects, you can also go with C array with id type but you have to manage memory allocation/deallocation yourself. 2 and 3 are better way to do this.
FYI:
2D arrays using NSMutableArray
Creating a two dimensional array in Objective-C
in iOS 6 you can use subscript to define a matrix class that uses the square bracket syntax matrix[row][col] where you can store objects and they are correctly retained by the matrix, differently than using a C array
First create a Row object, defined like this
- (id)initWithElementNumber:(NSUInteger)num {
if (self = [super init]) {
_row = [NSMutableArray arrayWithCapacity:num];
for (int j = 0; j < num; j++)
[_row addObject:[NSNull null]];
}
return self;
}
- (id)objectAtIndexedSubscript:(NSUInteger)idx {
return self.row[idx];
}
- (void)setObject:(id)object atIndexedSubscript:(NSUInteger)idx {
self.row[idx] = object;
}
#end
And then a Matrix class that uses the Row class previously defined:
#implementation UKMatrix
- (id)initWithRows:(NSUInteger)numRows columsn:(NSUInteger)numCol {
if (self = [super init])
{
_numCol = numCol;
_numRows = numRows;
_rows = [NSMutableArray arrayWithCapacity:numRows];
for (int j = 0; j < numRows; j++)
[_rows addObject:[[UKRow alloc] initWithElementNumber:numCol]];
}
return self;
}
- (id)objectAtIndexedSubscript:(NSUInteger)idx {
return self.rows[idx];
}
- (NSString *)description {
NSString *matrixDesc = #"";
for (int j = 0; j < self.numRows; j++) {
matrixDesc = [matrixDesc stringByAppendingString:#"\n"];
for (int k = 0; k < self.numCol; k++)
matrixDesc = [matrixDesc stringByAppendingFormat:#" %# ",self[j][k]];
}
return matrixDesc;
}
#end
then you can use the Matrix with the following syntax
UKMatrix *matrix = [[UKMatrix alloc] initWithRows:4 columsn:2];
matrix[1][1] = #2;
NSLog(#"%#", matrix);
I have an NSObject subclass in which I implemented the isEqual: and hash methods as follows for testing purposes:
- (BOOL)isEqual:(id)anObject {
return YES;
}
- (NSUInteger)hash {
return 1;
}
For some reason, I can add multiple objects of this class to an NSMutableSet even though they are the "same". Is there any reason this would not be working?
Update: It turns out I was assigning an NSMutableArray instance to an ivar of type NSMutableSet. D'oh!
There must be something else in your code that you are not doing right, because overriding methods as you show in the OP causes NSMutableSet to recognize my objects as identical:
Test.h:
#import "Foundation/Foundation.h"
#interface Test : NSObject
#end
Test.m:
#import "Test.h"
#implementation Test
- (BOOL)isEqual:(id)anObject {
return YES;
}
- (NSUInteger)hash {
return 1;
}
#end
main.c:
#include <CoreFoundation/CoreFoundation.h>
#import "Test.h"
int main (int argc, const char * argv[]) {
Test *t1 = [[Test alloc] init];
Test *t2 = [[Test alloc] init];
Test *t3 = [[Test alloc] init];
Test *t4 = [[Test alloc] init];
NSSet *s = [NSMutableSet setWithObjects:t1, t2, t3, t4, nil];
NSLog(#"%lu", s.count);
return 0;
}
This snippet produces 1, as expected.
The addObject method returns void and provides no sort of feedback as to whether or not the item actually got "added".
- (void)addObject:(id)object
Are you enumerating the set to determine that the object(s) were "added twice"? Otherwise, what leads you to believe they are?
If two sets were unioned together with unionSet should an error occur if both sets contain the same object? Or should the result simply include the same object both original sets included?
What if you were to union a set of exactly one item? Because if you agree with the above, then you'll understand why I say the following...
I think it's just silently swallowing the second addObject attempt (the way it's supposed to) and moving on with life.
Is there a way to force NSMutableArray to hold one specific object type only?
I have classes definitions as follow:
#interface Wheel:NSObject
{
int size;
float diameter;
}
#end
#interface Car:NSObject
{
NSString *model;
NSString *make;
NSMutableArray *wheels;
}
#end
How can I force wheels array to hold Wheel objects only with code? (and absolutely not other objects)
Update in 2015
This answer was first written in early 2011 and began:
What we really want is parametric polymorphism so you could declare, say, NSMutableArray<NSString>; but alas such is not available.
In 2015 Apple apparently changed this with the introduction of "lightweight generics" into Objective-C and now you can declare:
NSMutableArray<NSString *> *onlyStrings = [NSMutableArray new];
But all is not quite what it seems, notice the "lightweight"... Then notice that the initialisation part of the above declaration does not contain any generic notation. While Apple have introduced parametric collections, and adding a non-string directly to the above array, onlyStrings, as in say:
[onlyStrings addObject:#666]; // <- Warning: Incompatible pointer types...
will illicit the warning as indicated, the type security is barely skin deep. Consider the method:
- (void) push:(id)obj onto:(NSMutableArray *)array
{
[array addObject:obj];
}
and the code fragment in another method of the same class:
NSMutableArray<NSString *> *oops = [NSMutableArray new];
[self push:#"asda" onto:oops]; // add a string, fine
[self push:#42 onto:oops]; // add a number, no warnings...
What Apple have implemented is essentially a hinting system to assist with automatic inter-operation with Swift, which does have a flavour of type-safe generics. However on the Objective-C side, while the compiler provides some extra hints the system is "lightweight" and type-integrity is still ultimately down to the programmer - as is the Objective-C way.
So which should you use? The new lightweight/pseudo generics, or devise your own patterns for your code? There really is no right answer, figure out what makes sense in your scenario and use it.
For example: If you are targeting interoperation with Swift you should use the lightweight generics! However if the type integrity of a collection is important in your scenario then you could combine the lightweight generics with your own code on the Objective-C side which enforces the type integrity that Swift will on its side.
The Remainder of the 2011 Answer
As another option here is a quick general subclass of NSMutableArray which you init with the kind of object you want in your monomorphic array. This option does not give you static type-checking (in as much as you ever get it in Obj-C), you get runtime exceptions on inserting the wrong type, just as you get runtime exceptions for index out of bounds etc.
This is not thoroughly tested and assumes the documentation on overriding NSMutableArray is correct...
#interface MonomorphicArray : NSMutableArray
{
Class elementClass;
NSMutableArray *realArray;
}
- (id) initWithClass:(Class)element andCapacity:(NSUInteger)numItems;
- (id) initWithClass:(Class)element;
#end
And the implementation:
#implementation MonomorphicArray
- (id) initWithClass:(Class)element andCapacity:(NSUInteger)numItems
{
elementClass = element;
realArray = [NSMutableArray arrayWithCapacity:numItems];
return self;
}
- (id) initWithClass:(Class)element
{
elementClass = element;
realArray = [NSMutableArray new];
return self;
}
// override primitive NSMutableArray methods and enforce monomorphism
- (void) insertObject:(id)anObject atIndex:(NSUInteger)index
{
if ([anObject isKindOfClass:elementClass]) // allows subclasses, use isMemeberOfClass for exact match
{
[realArray insertObject:anObject atIndex:index];
}
else
{
NSException* myException = [NSException
exceptionWithName:#"InvalidAddObject"
reason:#"Added object has wrong type"
userInfo:nil];
#throw myException;
}
}
- (void) removeObjectAtIndex:(NSUInteger)index
{
[realArray removeObjectAtIndex:index];
}
// override primitive NSArray methods
- (NSUInteger) count
{
return [realArray count];
}
- (id) objectAtIndex:(NSUInteger)index
{
return [realArray objectAtIndex:index];
}
// block all the other init's (some could be supported)
static id NotSupported()
{
NSException* myException = [NSException
exceptionWithName:#"InvalidInitializer"
reason:#"Only initWithClass: and initWithClass:andCapacity: supported"
userInfo:nil];
#throw myException;
}
- (id)initWithArray:(NSArray *)anArray { return NotSupported(); }
- (id)initWithArray:(NSArray *)array copyItems:(BOOL)flag { return NotSupported(); }
- (id)initWithContentsOfFile:(NSString *)aPath { return NotSupported(); }
- (id)initWithContentsOfURL:(NSURL *)aURL { return NotSupported(); }
- (id)initWithObjects:(id)firstObj, ... { return NotSupported(); }
- (id)initWithObjects:(const id *)objects count:(NSUInteger)count { return NotSupported(); }
#end
Use as:
MonomorphicArray *monoString = [[MonomorphicArray alloc] initWithClass:[NSString class] andCapacity:3];
[monoString addObject:#"A string"];
[monoString addObject:[NSNumber numberWithInt:42]]; // will throw
[monoString addObject:#"Another string"];
Since Xcode 7, generics are available in Objective-C.
You can declare a NSMutableArray as:
NSMutableArray <Wheel*> *wheels = [[NSMutableArray alloc] initWithArray:#[[Wheel new],[Wheel new]];
The compiler will give you a warning if you try to put non-Wheel objects in the array.
I could be wrong (I'm a noob), but I think, if you create a custom protocol and make sure the objects you are adding to the array follow the same protocol, then when you declare the array you use
NSArray<Protocol Name>
That should prevent objects being added that do not follow the said protocol.
as per i know.. before you added any object in wheels mutableArray, u have to add some check mark. Is the object which i am adding is class "wheel". if it is then add, other wise not.
Example:
if([id isClassOf:"Wheel"] == YES)
{
[array addObject:id)
}
Something like this. i dont remember the exact syntax.
I hope this will help (and work... :P )
Wheel.h file:
#protocol Wheel
#end
#interface Wheel : NSObject
#property ...
#end
Car.h file:
#import "Wheel.h"
#interface Car:NSObject
{
NSString *model;
NSString *make;
NSMutableArray<Wheel, Optional> *wheels;
}
#end
Car.m file:
#import "Car.h"
#implementation Car
-(id)init{
if (self=[super init]){
self.wheels = (NSMutableArray<Wheel,Optional>*)[NSMutableArray alloc]init];
}
return self;
}
#end
Xcode 7 allows you to define Arrays, Dictionaries, and even your own Classes as having generics. The array syntax is as follows:
NSArray<NSString*>* array = #[#"hello world"];
I don't believe there's any way to do it with NSMutableArray out of the box. You could probably enforce this by subclassing and overriding all the constructors and insertion methods, but it's probably not worth it. What are you hoping to achieve with this?
That's not possible; an NSArray (whether mutable or not) will hold any object type. What you can do is to create your own custom subclasses as already suggested by Jim. Alternatively, if you wanted to filter an array to remove objects that weren't of the type you want, then you could do:
- (void)removeObjectsFromArray:(NSMutableArray *)array otherThanOfType:(Class)type
{
int c = 0;
while(c < [array length])
{
NSObject *object = [array objectAtIndex:c];
if([object isKindOfClass:type])
c++;
else
[array removeObjectAtIndex:c];
}
}
...
[self removeObjectsFromArray:array otherThanOfType:[Car class]];
Or make other judgments based on the result of isKindOfClass:, e.g. to divide an array containing a mixture of Cars and Wheels into two arrays, each containing only one kind of object.
You can use the nsexception if you dont have the specific object.
for (int i = 0; i<items.count;i++) {
if([[items objectAtIndex:i] isKindOfClass:[Wheel class]])
{
// do something..!
}else{
[NSException raise:#"Invalid value" format:#"Format of %# is invalid", items];
// do whatever to handle or raise your exception.
}
}
Here's something I've done to avoid subclassing NSMutableArray: use a category. This way you can have the argument and return types you want. Note the naming convention: replace the word "object" in each of the methods you will use with the name of the element class. "objectAtIndex" becomes "wheelAtIndex" and so on. This way there's no name conflict. Very tidy.
typedef NSMutableArray WheelList;
#interface NSMutableArray (WheelList)
- (wheel *) wheelAtIndex: (NSUInteger) index;
- (void) addWheel: (wheel *) w;
#end
#implementation NSMutableArray (WheelList)
- (wheel *) wheelAtIndex: (NSUInteger) index
{
return (wheel *) [self objectAtIndex: index];
}
- (void) addWheel: (wheel *) w
{
[self addObject: w];
}
#end
#interface Car : NSObject
#property WheelList *wheels;
#end;
#implementation Car
#synthesize wheels;
- (id) init
{
if (self = [super init]) {
wheels = [[WheelList alloc] initWithCapacity: 4];
}
return self;
}
#end
protocol maybe a good idea:
#protocol Person <NSObject>
#end
#interface Person : NSObject <Person>
#end
to use:
NSArray<Person>* personArray;
There is one-header file project which allows this:
Objective-C-Generics
Usage:
Copy ObjectiveCGenerics.h to your project.
When defining a new class use the GENERICSABLE macro.
#import "ObjectiveCGenerics.h"
GENERICSABLE(MyClass)
#interface MyClass : NSObject<MyClass>
#property (nonatomic, strong) NSString* name;
#end
Now you can use generics with arrays and sets just as you normally do in Java, C#, etc.
Code: