I'm using SortedDictionaries to simulate a Queue (due to some requirements that I have), and I'm calling Last() over the sorted dictionary to get the item that I need to dequeue.
I was just wondering about the performance of using a custom comparer and calling First() or keep calling Last().
After decompiling the .NET 3.5 assemblies, I found that the SortedDictionary class does have a Count property, so I'm guessing the framework just returns the item at position 0 when First is called, and the item at position [count-1] when Last is called, am I right?
No.
Since SortedDictionary does not implement IList<TValue> (which has a this[int] indexer), Last() has no choice but to iterate through the whole thing.
The Last method is an extension method in the Enumerable class. The implementation of Last first tries to cast the IEnumerable (your SortedDictionary) to IList<T>. If it can, then it uses the Count property to directly access the last element. If it can't, then it has to iterate over all elements to get to the last one. SortedDictionary doesn't implement IList<T>, so Last will iterate over all elements.
Related
In the oracle Java docs: https://docs.oracle.com/javase/8/docs/api/java/util/LinkedList.html:
.element() "Retrieves, but does not remove, the head (first element) of this list."
.peek() "Retrieves, but does not remove, the head (first element) of this list."
Is there a reason that you would want to use .element() as opposed to .peek()?
Is the answer to (1) is "No", why would a class need two methods with the same function?
There are 4 methods.
Peek
Element
Poll
Remove
The behaviour of peek and element is almost same with a difference:
If a queue doesnt contain any elements the peek() method returns null.
The element() method behaves like peek(), so it again retrieves the value of the first element without removing it.
However, if the list is empty element() throws a NoSuchElementException.
Lastly, there are two other methods poll and remove.
The poll() method retrieves the value of the first element of the queue by removing it from the queue. If the list doesnt contain any elements, it will return null but doesnt throw any exception.
The remove() method behaves as the poll() method, so it removes the first element of the list and if the list is empty it will throw a NoSuchElementException.
Reference:
http://www.davismol.net/2014/04/04/java-ocpjp7-difference-between-element-peek-poll-and-remove-methods-of-the-queue-interface/
The behavior is described in the docs for Queue. Basically element throws an exception if there is an error (think empty list) whereas peek just returns a special value (probably null). https://docs.oracle.com/javase/7/docs/api/java/util/Queue.html
I am retrieving a list of items using Entity Framework and if there are some items retrieved I do something with them.
var items = db.MyTable.Where(t => t.Expiration < DateTime.Now).ToList();
if(items.Count != 0)
{
// Do something...
}
The if statement could also be written as
if(items.Count() != 0)
{
// Do something...
}
In the first case, the .Count is a List<T>.Count property. In the second case, the .Count() is IEnumerable<T>.Count() extension method.
Although both approaches achieve the same result, however, is one more preferred than the other? (Possibly some difference in performance?)
Enumerable.Count<T> (the extension method for IEnumerable<T>) just calls Count if the underlying type is an ICollection<T>, so for List<T> there is no difference.
Queryable.Count<T> (the extension method for IQueryable<T>) will use the underlying query provider, which in many cases will push the count down to the actual SQL, which will perform faster than counting the objects in memory.
If a filter is applied (e.g. Count(i => i.Name = "John")) or if the underlying type is not an ICollection<T>, the collection is enumerated to compute the count.
is one more preferred than the other?
I generally prefer to use Count() since 1) it's more portable (the underlying type can be anything that implements IEnumerable<T> or IQueryable<T>) and 2) it's easier to add a filter later if necessary.
As Tim states in his comment, I also prefer using Any() to Count() > 0 since it doesn't have to actually count the items - it will just check for the existence of one item. Conversely I use !Any() instead of Count() == 0.
It depends on the underlying collection and where Linq will be pulling from. For example if it's SQL then using .ToList() will cause the query to pull back the entire list, and then count it. However, the .Count() extension method will translate it into a SQL COUNT statement on the database side. In which case there will be an obvious performance difference.
For just a standard List or Collection it's as stated in D. Stanley's answer.
I would say that it depends on what's going on inside the if block. If you're simply doing the check to determine whether to perform a sequence of operations on the underlying enumeration, then it's probably not needed in any event. Simply iterate over the enumeration (omitting ToList as well). If you're not using the collection inside the if block, then you should avoid using ToList and definitely use Any over any Count/Count() method.
Once you've performed the ToList then you're no longer using Entity Framework and I expect that Count() is only marginally slower than Count since, if the underlying collection is ICollection<T> it defers to that implementation. The only overhead would be determining whether it implements that interface.
http://msdn.microsoft.com/en-us/library/bb338038.aspx
Remarks:
If the type of source implements ICollection<T>, that implementation is used to obtain the count of elements. Otherwise, this method determines the count.
In my collection view I need to generate an index for each item. As Items get reordered I need this index to update with its new position.
The data are Core Data entities in a managed NSArrayController.
The closest I have come to a possible solution is implementing this method on the entity class and then using representedObject.dynamicIndex to bind it to the UI.
- (NSNumber *) dynamicIndex
{
NSInteger r = [[[[self managedObjectContext] registeredObjects] allObjects] indexOfObject:self];
NSNumber *result = [NSNumber numberWithInt:r];
return result;
}
This solution is sketchy at best, and not really functional as it doesn't necessarily reflect the order in the collection view.
Anyone have a model / mechanism for generating or retrieving item indexes in an NSCollectionView?
First, make sure you understand the difference between (and properly use the terminology of) "entity" and "instance." It makes all the difference in communicating your problems/solutions with others.
Second: Don't worry about NSCollectionViewItems ... worry about each one's "represented object," which is held in some container.
Third: Did you want the display order to be a persistent attribute of your entity or do you just need to know what position the item is in at the moment, regardless of what it might be later? Important question.
Fourth: Core Data does not give you the concept of ordered collections. This is to support store types such as NSSQLiteStoreType, where you might only want to fault in a few items (or one) without loading the whole list. Therefore, you're on your own if you want a persistent sort order. To do this, just add an attribute to your entity called "sortOrder" and make it a number type.
Fifth: Because of the "no ordered collections" issue above, your attempt to find the index of a given instance of your entity from an array, built from a set, which was faulted in with a nondeterministic order is doomed to failure.
Sixth: Since you're using an array controller, you'll need to set its sort descriptors. You'll want to use your "sortOrder" key. That way, your fetched instances will always be kept sorted by their "sortOrder."
Seventh and finally: If you're trying to get the index of any objects in your array controller's set/array of objects, you'll want to ask it for its -arrangedObjects, so you're getting the index of the object in the sorted collection the array controller controls.
Hope that helps.
Update for Lion (10.7)
With regard to my sixth point: If you're targeting 10.7 and above in your application, [NSManagedObject now gives you ordered relationships.][1] Use -mutableOrderedSetValueForKey: and -mutableOrderedSetValueForKey: to set and retrieve NSOrderedSets. Yay!
Can it be advantageous for a method to return IOrderedEnumerable instead of IEnumerable?
Only if you expect people to order that enumerable every time and would find it hard to figure out how to do this OR if you can provide a collection that implements that interface that can efficiently order its contents and is paired with an extension method that is aware of your collection.
Best option is to return a specific collection type (see Richter for details on that). 99 times out of 100 whoever gets even a simple enumerable can use the standard linq extension methods to order it if they want.
Specifically, it would be worth doing if it makes sense for further .ThenBy calls, and not otherwise.
I have an object that implements the indexed accessor methods for a key called contents. In those accessors, I call willChange:valuesAtIndexes:forKey: and didChange:valuesAtIndexes:forKey: when I modify the underlying array.
I also have a custom view object that is bound to contents via an NSArrayController. In observeValueForKeyPath:ofObject:change:context: the only value in the change dictionary for the NSKeyValueChangeKindKey I ever see is NSKeyValueChangeSetting. When I'm adding objects to the array, I expect to see NSKeyValueChangeInsertion.
Recreating my view's internal representation of the objects it observes every time I insert a single item -- particularly when I'm bulk loading hundreds of items -- presents quite a performance problem, as you'd imagine. What am I doing wrong that Cocoa seems to think I'm setting a completely new array each time I add or remove a single item?
(Note to all readers: I hate using answers for this, too, but this discussion is too long for comments. The downside, of course, is that it ends up not sorted chronologically. If you don't like it, I suggest you complain to the Stack Overflow admins about comments being length-limited and plain-text-only.)
I don't understand what you mean by implementing array accessors in the view.
Implement accessors, including indexed accessors, for the mutable array property that you've exposed as a binding.
Bindings is built on top of KVO.
And KVC.
All bindings are implemented using observeValueForKeyPath:
Overriding that is one way, sure. The other way is to implement accessors in the object with the bindable property (the view).
My custom view provides a binding that the app binds to an array -- or in this case, an array controller. Accessor methods apply to KVC, not KVO.
Cocoa Bindings will call your view's accessors for you (presumably using KVC). You don't need to implement the KVO observe method (unless, of course, you're using KVO directly).
I know this because I've done it that way. See PRHGradientView in CPU Usage.
Curiously, the documentation doesn't mention this. I'm going to file a documentation bug about it—either I'm doing something fragile or they forgot to mention this very nice feature in the docs.
It absolutely matters that I'm getting a set message on every array update. I wouldn't have posted it as a question if it didn't matter.
There are quite a large number of people who engage in something called “premature optimization”. I have no way of knowing who is one of them without asking.
I have an object that implements the indexed accessor methods for a key called contents. In those accessors, I call willChange:valuesAtIndexes:forKey: and didChange:valuesAtIndexes:forKey: when I modify the underlying array.
Don't do that. KVO posts the notifications for you when you receive a message to one of those accessors.
I also have a custom view object that is bound to contents via an NSArrayController. In observeValueForKeyPath:ofObject:change:context: the only value in the change dictionary for the NSKeyValueChangeKindKey I ever see is NSKeyValueChangeSetting. When I'm adding objects to the array, I expect to see NSKeyValueChangeInsertion.
For one thing, why are you using KVO directly? Use bind:toObject:withKeyPath:options: to bind the view's property to the array controller's arrangedObjects (I assume) property, and implement array accessors (including indexed accessors, if you like) in the view.
For another, remember that arrangedObjects is a derived property. The array controller will filter and sort its content array; the result is arrangedObjects. You could argue that permuting the indexes from the original insertion into a new insertion would be a more accurate translation of the first change into the second, but setting the entire arrangedObjects array was probably simpler to implement (something like [self _setArrangedObjects:[[newArray filteredArrayUsingPredicate:self.filterPredicate] sortedArrayUsingDescriptors:self.sortDescriptors]]).
Does it really matter? Have you profiled and found that your app is slow with wholesale array replacement?
If so, you may need to bind the view directly to the array's content property or to the original array on the underlying object, and suffer the loss of free filtering and sorting.
I call the KVO methods manually for reasons outside the scope of this issue. I have disabled automatic observing for this property. I know what I'm doing there.
I don't understand what you mean by implementing array accessors in the view. Bindings is built on top of KVO. All bindings are implemented using observeValueForKeyPath: My custom view provides a binding that the app binds to an array -- or in this case, an array controller. Accessor methods apply to KVC, not KVO.
It absolutely matters that I'm getting a set message on every array update. I wouldn't have posted it as a question if it didn't matter. I call something like
[[modelObject mutableArrayValueForKey:#"contents"] addObjectsFromArray:hundredsOfObjects];
On every insertion, my view observes a whole new array. Since I'm potentially adding hundreds of objects, that's O(N^2) when it should to be O(N). That is completely unacceptable, performance issues aside. But, since you mention it, the view does have to do a fair amount of work to observe a whole new array, which significantly slows down the program.
I can't give up using an array controller because I need the filtering and sorting, and because there's an NSTableView bound to the same controller. I rely on it to keep the sorting and selections in sync.
I solved my problem with a complete hack. I wrote a separate method that calls the KVO methods manually so that only one KVO message is sent. It's a hack, I don't like it, and it still makes my view reread the entire array -- although only once, now -- but it works for now until I figure out a better solution.