I wish in my class to return a list from a dictionary but allow custom sorting using pre-written comparison methods. In my original java code that I'm converting from, I created compare methods using Google Guava Ordering in my class and then had a single method called the following passing in one of the public comparator methods, kind of declared like this:
public List<Word> getWords(Comparator c) { }
I'm trying to recreate this in C# but I can't figure out how. Essentially in the code below you can see there are three versions for each type of sort, and in addition I end up creating two lists for every return value which seems a bit wasteful.
I looked at creating delegates but got a bit lost, then figured I could create an IComparable, but then saw IComparator and then saw Sort method takes a Comparator.
Can somebody point me in the direction of converting this into a single sort 'GetWords' in the best way, allowing clients to call the GetWords retrieving a sorted list from a pre-supplied set of ordering.
public partial class WordTable
{
private Dictionary<string, Word> words;
public WordTable()
{
//for testing
words = new Dictionary<string, Word>();
words.Add("B", new Word("B", WordTypes.Adjective));
words.Add("A", new Word("A", WordTypes.Noun));
words.Add("D", new Word("D", WordTypes.Verb));
}
public List<Word> GetWords()
{
return words.Values.ToList();
}
public List<Word> GetWordsByName()
{
List<Word> list = words.Values.ToList<Word>();
return list.OrderBy(word => word.Name).ToList();
}
public List<Word> GetWordsByType()
{
List<Word> list = words.Values.ToList<Word>();
return list.OrderBy(word => word.Type).ToList();
}
}
I think you are looking for predicates.
Effectively, you want a predefined set of predicates (one for ByName, one for ByType), and you pass this predicate into the GetWords function.
There are two approaches you can use.
IComparer
This is more closely related to your past Java experience.
The official way is to use IComparer<T> (link).
Similar to your Comparator in the Java example, this enables you to create different sorting methods which all implement the IComparer<Word> interface, and then you can dynamically choose your sorting method.
As a simple example:
public class WordNameComparer : IComparer<Word>
{
public int Compare(Word word1, Word word2)
{
return word1.Name.CompareTo(word2.Name);
}
}
And then you can do:
public List<Word> GetWords(IComparer<Word> comparer)
{
return words.Values.OrderBy(x => x, comparer).ToList();
}
Which you can call by doing:
var table = new WordTable();
List<Word> sortedWords = table.GetWords(new WordNameComparer());
And of course you change the sorting logic by passing a different IComparer<Word>.
Func parameters
From experience, this is a much preferred approach due to LINQ's enhanced readability and low implementation cost.
Looking at your last two methods, you should see that the only variable part is the lambda method that you use to order the data. You can of course turn this variably into a method parameter:
public List<Word> GetWordsBy<T>(Func<Word,T> orderByPredicate)
{
return words.Values.OrderBy(orderBy).ToList();
}
Because the OrderBy predicate uses a generic parameter for the selected property (e.g. sorting on a string field? an int field? ...), you have to make this method generic, but you don't need to explicitly use the generic parameter when you call the method. For example:
var sortedWordsByName = table.GetWordsBy(w => w.Name);
var sortedWordsByLength = table.GetWordsBy(w => w.Name.Length);
var sortedWordsByType = table.GetWordsBy(w => w.Type);
Note that if you select a class, not a value type, that you will either still have to create and pass an IComparer<> for this class, or the class itself must implement IComparable<> so it can be sorted the way you want it to be.
You can introduce ascending/descending ordering:
public List<Word> GetWordsBy<T>(Func<Word,T> orderByPredicate, bool sortAscending = true)
{
return sortAscending
? words.Values.OrderBy(orderBy).ToList()
? words.Values.OrderByDescending(orderBy).ToList();
}
Update
I was trying to do it with delegates, but avoiding the caller having to roll their own lambda statement and use predefined ones.
You can simply wrap your method with some predefined options:
public List<Word> GetWordsBy<T>(Func<Word,T> orderByPredicate)
{
return words.Values.OrderBy(orderBy).ToList();
}
public List<Word> GetWordsByName()
{
return GetWordsBy(w => w.Name);
}
This way, your external callers don't need to use the lambda if they don't want to; but you still retain the benefits of having reusable code inside your class.
There are many ways to do this. I prefer creating preset methods for readability's sake, but you could instead have an enum which you then map to the correct Func. Or you could create some static preset lambdas which the external caller can reference. Or... The world is your oyster :-)
I hope this works, or even compiles.
class WordTable
{
public List<Word> GetWords(IComparer<Word> comparer)
{
return words.Values.OrderBy(x => x, comparer).ToList();
}
}
class WordsByNameAndThenTypeComparer : IComparer<Word>
{
public override int Compare(Word x, Word y)
{
int byName = x.Name.CompareTo(y.Name);
return byName != 0 ? byName : x.Type.CompareTo(y.Type);
}
}
Usage:
WordTable wt = new WordTable();
List<Words> words = wt.GetWords(new WordsByNameAndThenTypeComparer());
Related
I am adding some localization logic that I want to use application wide and instead of creating it multiple times I have decided to create a Generic method for this scenario and it works, but my Generics knowledge is limited, and it just doesn't feel optimal...
Method:
public List<T> Localize<T>(List<T> inputList, string propertyName)
{
var filteredList = new List<T>();
foreach (var item in inputList)
{
var clone = Mapper.Map<T, T>(item);
// "TranslationKey" is the fixed/same column name for every entity/table.
var translationKey = item.GetType().GetProperty("TranslationKey").GetValue(clone).ToString();
if (!string.IsNullOrEmpty(translationKey))
{
var prop = clone.GetType().GetProperty(propertyName);
prop.SetValue(clone, TranslateAsync(translationKey).Result);
}
filteredList.Add(clone);
}
return filteredList;
}
Then I would call the method like so:
var items = Localize(itemsList, "Description"); // To localize "Description" prop
var people = Localize(peopleList, "Name"); // To localize "Name" prop of People list...
So my two main questions are:
Can I optimize my methods implementation?
Is there a way I could not hard code property names when calling the method or is there a better/faster LINQ way or something I am missing?
Since reflection is used for getters/setters, which can probably be avoided, there is indeed room for optimization and more importantly making the code safer in case objects are changed in the future.
The first reflection item.GetType().GetProperty("TranslationKey").GetValue(clone) implies that type T always has a property TranslationKey. The generic constraints can enforce that, as long as all objects implement the proper interface (or share the same base class)
For example, the Item class and People class both implement something like interface ITranslationEntity{string TranslationKey{get;}} and if the method signature contains where T:ITranslationEntity, the property can be accessed directly
The setter could be done with the same interface implementation, e.g. have a SetTranslatedValue(string) on the interface, or the setter can be implemented as a lambda public List<T> Localize<T>(List<T> inputList, Action<T,string> setter) Used the latter as an example here, but having it in the interface would personally seem the better choice.
A small extra change which could make the call easier, but depends on whether you can place this method in a static class, is to make the method an extension method.
Perhaps the most important part is that the async call is executed synchronously in the loop (by accessing the Result ). Perhaps the implementation isn't truly asynchronous, but if it is, the major optimization is to combine the async calls and await the set of Tasks (and set the result inside a ContinueWith
End result:
static class SomeClass
{
public static List<T> Localize<T>(this List<T> inputList, Action<T,string> setter)
where T:ITranslationEntity
{
var clonedList = inputList.Select(Mapper.Map<T,T>).ToList();
var tasks = (from clone in clonedList
let key = clone.TranslationKey
where key != null
select TranslateAsync(key).ContinueWith(t=> setter(clone,t.Result))).ToArray();
Task.WaitAll(tasks);
return clonedList;
}
}
Example call:
var items = itemsList.Localize((i,val) =>i.Description = val);
Again, the setter is just an alternative and implementing that in other ways might be better, but the major point is to avoid reflection whenever possible and if async code is called for multiple items, to await the result of the combined tasks.
Can I optimize my methods implementation?
Well, that depends on what you mean by "optimize". I think you can convert your foreach loop into a LINQ Select call followed by a Where call to filter out the nulls.
Is there a way I could not hard code property names when calling the method or is there a better/faster LINQ way or something I am missing?
I suggest using the nameof operator when you pass the property name, so instead of this:
var items = Localize(itemsList, "Description");
You can do this:
var items = Localize(itemsList, nameof(Description));
This way, you can avoid hard coding the strings!
Firstly, using reflection to reset some property is far from being optimized. You probably need to refactor to some kind of Visitor so eventually your code will look like:
new EnglishVisitor.Visit(myObject);
As I see, your classes are responsible for providing some sort of TrnslationKey, right? So next step is to extract appropriate interface:
publuc interface ITranslationKeyProvider { string GetTranslationKey(); }
...and this gives you an opportunity to make it more safe with helps of generics:
public T Visit<T>(T object) where T : ITranslationKeyProvider
so the compiler won't let you to pass something completely different.
It will be much much much more better if you use dynamic keyword to defer type-check up to runtime moment.
Regarding your generics. Thet are perfectly fine.
It seems from your design that TranslationKey can be used to localize exactly one property for each entity, so the following does not make sense:
Localize(itemsList, "Description");
Localize(itemsList, "Title"); // cannot do that, because only description is localizable
If that is the case - you don't need to specify property to localize when calling the method. Instead, use interface like this:
public interface ITranslatable {
string TranslationKey { get; }
string TranslatedProperty { get; set; }
}
class MyEntity : ITranslatable {
public string TranslationKey { get; set; }
public string Description { get; set; }
// implicit implementation to avoid clutter
string ITranslatable.TranslatedProperty
{
get { return Description; }
set { Description = value; }
}
}
And your Localize method does not need any reflection any more:
public static List<T> Localize<T>(List<T> inputList) where T:ITranslatable
{
var filteredList = new List<T>();
foreach (var item in inputList) {
var clone = Mapper.Map<T, T>(item);
// "TranslationKey" is the fixed/same column name for every entity/table.
if (!string.IsNullOrEmpty(clone.TranslationKey))
clone.TranslatedProperty = TranslateAsync(clone.TranslationKey).Result;
filteredList.Add(clone);
}
return filteredList;
}
There are several points you could address:
1. TranslationKey property
When using something like item.GetType().GetProperty("TranslationKey").GetValue(clone) in a generic method, that means the type is always constained to have a TranslationKey property. I would suggest to use some interface and generic constraint for improving both speed and add a compile-time checks. For example:
public interface ITranslatable
{
string TranslationKey { get; }
}
usage:
public void Translate<T>(T value) where T : ITranslatable
{
var translationKey = value.TranslationKey;
...
}
This might not be possible to achieve though, especially when using 3rd party types.
2. Retrieving PropertyInfo in each iteration
Your code seems to be always accessing the same property for each element of the collection passed in:
foreach (var item in items)
{
var clone = Mapper.Map<T, T>();
...
var prop = clone.GetType().GetProperty(propertyName);
...
}
You can simply load the property only once for each method call outside of the foreach, this will save some time on the reflection (especially on big collections). If you wanted to optimize for speed further, you could also cache the properties for given type, but I wouldn't recommend it as a starter.
This may not be valid if Mapper.Map<T, T> can actually take and return a type that is more derived than T and hides the propertyName property (e.g. via new keyword).
3. List size
Additional minor point is that you allocate the filteredList without any size hint, yet the size is known, it is the size of inputList. This can save some time on big collections. In addition, the type of inputList parameter can be IReadOnlyCollection, improving the signature to reflect what is being done with it.
LINQ
I would oppose against LINQ usage here because of the prop.SetValue(clone, TranslateAsync(translationKey).Result); side-effect in your foreach loop. You could still return IReadOnlyCollection or IReadOnlyList from the method though, leading to a better flow on usage places.
Final code
public IReadOnlyCollection<T> Localize<T>(IReadOnlyCollection<T> inputList, string propertyName) where T : ITranslatable
{
var prop = typeof(T).GetProperty(propertyName);
var filteredList = new List<T>(inputList.Count);
foreach (var item in inputList)
{
var clone = Mapper.Map<T, T>(item);
// "TranslationKey" is the fixed/same column name for every entity/table.
var translationKey = clone.TranslationKey;
if (!string.IsNullOrEmpty(translationKey))
{
prop.SetValue(clone, TranslateAsync(translationKey).Result);
}
filteredList.Add(clone);
}
return filteredList;
}
Adding this answer (arrived from other answers) as yet another alternative for future, this way I can expose Localize to Singular and Multiple objects:
public List<T> Localize<T>(List<T> inputList, Action<T, string> setter) where T : ITranslatable
{
return inputList.Select(a => Localize(a, setter)).ToList();
}
public T Localize<T>(T input, Action<T, string> setter) where T : ITranslatable
{
var clone = Mapper.Map<T, T>(input);
var translationKey = clone.TranslationKey;
if (!string.IsNullOrEmpty(translationKey))
{
setter(clone, TranslateAsync(translationKey).Result);
}
return clone;
}
Interface:
public interface ITranslatable
{
string TranslationKey{ get; }
}
Call like this:
Localize(items, (i, val) => i.Description= val); // etc.
OK so I'm fairly new to unit testing and everything is going well until now.
I'm simplifying my problem here, but basically I have the following:
[Test]
public void ListTest()
{
var expected = new List<MyClass>();
expected.Add(new MyOtherClass());
var actual = new List<MyClass>();
actual.Add(new MyOtherClass());
Assert.AreEqual(expected,actual);
//CollectionAssert.AreEqual(expected,actual);
}
But the test is failing, shouldn't the test pass? what am I missing?
If you're comparing two lists, you should use test using collection constraints.
Assert.That(actual, Is.EquivalentTo(expected));
Also, in your classes, you will need to override the Equals method, otherwise like gleng stated, the items in the list are still going to be compared based on reference.
Simple override example:
public class Example
{
public int ID { get; set; }
public override bool Equals(object obj)
{
return this.ID == (obj as Example).ID;
}
}
A very simple way to get this test to work is to only create the MyOtherClass instance once. That way, when comparing the item in the two lists they will be "equal" (because they reference the same object). If you do this, CollectionAssert will work just fine.
[Test]
public void ListTest()
{
var thing = new MyOtherClass();
var expected = new List<MyClass>();
expected.Add(thing);
var actual = new List<MyClass>();
actual.Add(thing);
CollectionAssert.AreEqual(expected,actual);
}
If you don't this though, you'll need to implement IEquatable<MyOtherClass> in MyOtherClass or override Equals to define what makes two instances of that class the "same".
Try to be a bit more specific about what you are trying to achieve. Explicitly telling that you want to compare entire sequence will solve the problem. I personally wouldn't rely on NUnit fancy features for determining what you meant by says AreEqual. E.g.
Assert.IsTrue(actual.SequenceEqual(expected));
I convert my comment to answer on request.
Well, this fails because AreEqual uses reference comparison. In order to make it work you need value comparison(your own custom comparison).
You can pretty much do that by implementing IEquatable interface. and keep in mind when you're implementing this interface you must override Object.Equals and Object.GetHashCode as well to get consistent results.
.Net framework supports doing this without implementing IEquatable you need IEqualityComparer that should do the trick, but nunit should have a method which takes this as a overload. Am not certain about "nunit" though.
From Nunit documentation:
Starting with version 2.2, special provision is also made for comparing single-dimensioned arrays. Two arrays will be treated as equal by Assert.AreEqual if they are the same length and each of the corresponding elements is equal. Note: Multi-dimensioned arrays, nested arrays (arrays of arrays) and other collection types such as ArrayList are not currently supported.
You have a list of objects ... so it's not the same as comparing 2 ints.
What you should do is probably compare all the objects inside the list ... (Try converting your list to an array ... might actually work :) )
As I said (and most others as well), you'll probably need to override Equals. Here's MSDN page about how to do it (Covers Equals, == operator, and GetHashCode).
Similar with more info :
[compare-equality-between-two-objects-in-nunit]
(Compare equality between two objects in NUnit)
If you can't modify a class then this example can be helpful:
[Test]
public void Arrays_Should_Be_Equal()
{
MyClass[] array1 = GetTestArrayOfSize(10);
MyClass[] array2 = GetTestArrayOfSize(10);
// DOESN'T PASS
// Assert.That(array1, Is.EquivalentTo(array2));
Func<MyClass, object> selector = i => new { i.Property1, i.Property2 };
Assert.That(array1.Select(selector), Is.EquivalentTo(array2.Select(selector)));
}
private MyClass[] GetTestArrayOfSize(int count)
{
return Enumerable.Range(1, count)
.Select(i => new MyClass { Property1 = "Property1" + i, Property2 = "Property2" + i }).ToArray();
}
Option 1: AreEquivalent
CollectionAssert.AreEquivalent(expectedList, actualList);
Option 2: IEqualityComparer - for custom equality comparisons
Assert.That(expectedList, Is.EqualTo(actualList).Using(new IEqualityComparerImplementation()));
private class IEqualityComparerImplementation: IEqualityComparer<T>
{
public bool Equals(GeometricPlane plane1, GeometricPlane plane2)
{
// obviously add in your own implementation
throw new NotImplementedException();
}
public int GetHashCode(GeometricPlane obj)
{
throw new NotImplementedException();
}
}
How do I convert
public class MyCustomList: List<MyCustomList>
back to MyCustomList after ordering?
myCustomListObject = myCustomListObject.OrderBy(...);
I tried .ToList() as myCustomListObject which returns null. What should I do?
public class MyCustomList: List<MyCustomList>
{
//stuff you already have here, including your current constructors
public MyCustomList(IEnumerable<MyCustomList> source)
{
//something here that (perhaps after using `this` to call
//one of the existing constructors, loads all of the items
//in source into it. There may be optimisations available
//in particular cases, as a bonus.
}
}
If you really want to be able to do something like the ToList() style, then you can add:
public static class MyBigOClassOHelpfulStaticMethods //maybe pick a better name
{
public static MyCustomList ToMyCustomList(this IEnumerable<MyCustomList> source)
{
return new MyCustomList(source);
}
}
Which isn't far off how ToList() works.
All this said though, if you are going to be often writing over the first MyCustomList with the new one, then there'd be something to gain by calling Sort instead of OrderBy, as Sort will sort the list in-place.
The problem is that ToList() will return a List. You cannot convert it to a MyCustomList just like you cannot convert another object some somthing that it isnt.
List<string> result = myCustomListObject.OrderBy(...).ToList();
If you really need a MyCustomListObject you should create a constructor that accepts a explicit cast operation.
If MyCustomList is just another name for List<string> you could use:
using MyCustomList = List<string>;
Then it will work like you want it to.
The return value of OrderBy simply is no instance of MyCustomList, and neither is the return value of ToList. Therefore, you cannot cast it to MyCustomList.
The only options you have are:
You create a new instance of MyCustomList and add the elements returned by OrderBy.
You replace the current contentes of your MyCustomList instance with the elements returned by OrderBy.
Without knowing more about your MyCustomList class, it is impossible to tell more. As it inherits from List<MyCustomList>, however, it can be assumed that both of the above options are feasible.
I agree with O. R. Mapper in that, without knowing more about MyCustomList, it's hard to answer. But you could just do something simple like this (again, without knowing more, this may now work):
void Main()
{
var list = new MyList() { new Stuff() { ugg = "z" }, new Stuff() { ugg = "b" } };
var myOrderedList = list.OrderBy(s => s.ugg);
myOrderedList.ToList().Dump();
var list2 = new MyList();
list2.AddRange(myOrderedList);
list2.GetType().Name.Dump();
}
public class Stuff{
public string ugg {get;set;}
}
// Define other methods and classes here
public class MyList : List<Stuff>{
}
I use LinqPad to display the contents and type names using the Dump() extension method.
I have this class (a partial listing):
class CiscoSwitch
{
private string _SwitchName = string.Empty;
public SwitchName {get {return _SwitchName;} set{_SwitchName=value; }}
}
I have 2 lists of CiscoSwitch objects. I am trying to compare them to pick out the ones that are not duplicates. I only want the duplicates. I tried a Lambda expression but got a compiler error that CiscoSwitch was a non-delgate type.
I am now wondering about something like this - it would allow me to use the List.Except() method (I think):
static class SwitchComparer
{
static bool CompareSwitchNames(CiscoSwitch s1, CiscoSwitch s2)
{
if (sw1.SwitchName == s2.SwitchName) {return true;}
else {return false;}
}
}
// to find the differences
// this is a method of the CiscoSwitchClass
private List<CiscoSwitch> FindDifferences(List<CiscoSwitch> List1, List<CiscoSwitch> List2)
{
return List1.Except(List2, SwitchComparer.CompareSwitchNames();
}
this could also be done with a foreach but I think this way is a lot cleaner, if it is correct. I am also thinking there are other attributes of a CiscoSwitch I might want to compare some day so could add methods to the SwitchComparer class as I need them.
No, just having a single method like that won't help you. You need to implement an IEqualityComparer<CiscoSwitch> to pass to Enumerable.Except - and even then your code would need to be:
return List1.Except(List2, new SwitchComparer()).ToList();
Overriding Equals and GetHashCode within CiscoSwitch will do the trick more naturally though - and ideally you should implement IEquatable<CiscoSwitch> too.
However, it's worth noting that mutable types like this don't play terribly nicely with things like Dictionary<,> - if you change an object in a way which affects its hash code after you've inserted it as a key into the dictionary, you won't be able to get at it again. Consider making the type immutable if you can.
A couple of other points to note:
Any time you write:
if (condition)
{
return true;
}
else
{
return false;
}
you should instead write the far simpler:
return condition;
So your CompareSwitchNames method would be:
static bool CompareSwitchNames(CiscoSwitch s1, CiscoSwitch s2)
{
return s1.SwitchName == s2.SwitchName;
}
Your parameter names for FindDifferences should follow .NET naming conventions (e.g. list1 and list2)
Using Except will only find you the elements in the first list which aren't in the second list; if you need to find the symmetric difference, consider using HashSet<T> explicitly.
EDIT: If you wanted to have multiple ways of comparing, you could have something like:
public static class SwitchComparers
{
public static readonly IEqualityComparer<CiscoSwitch> ByName =
new ByNameComparer();
public static readonly IEqualityComparer<CiscoSwitch> ByCost =
new ByCostComparer();
private sealed class ByNameComparer : IEqualityComparer<CiscoSwitch>
{
// Implementation
}
private sealed class ByCostComparer : IEqualityComparer<CiscoSwitch>
{
// Implementation
}
}
You could implement a custom comparer:
public class CiscoSwitchComparer : IEqualityComparer<CiscoSwitch>
{
public bool Equals(CiscoSwitch x, CiscoSwitch y)
{
return x.SwitchName.Equals(y.SwitchName));
}
public int GetHashCode(CiscoSwitch obj)
{
return obj.SwitchName.GetHashCode();
}
}
And then:
private List<CiscoSwitch> FindDifferences(List<CiscoSwitch> List1, List<CiscoSwitch> List2)
{
return List1.Concat(List2)
.Distinct(new CiscoSwitchComparer())
.ToList();
}
You should implement IEqualityComparer[T] interface.
This interface allows the implementation of customized equality
comparison for collections. That is, you can create your own
definition of equality for type T, and specify that this definition be
used with a collection type that accepts the IEqualityComparer
generic interface. In the .NET Framework, constructors of the
Dictionary generic collection type accept this
interface.
A default implementation of this interface is provided by the Default
property of the EqualityComparer generic class. The StringComparer
class implements IEqualityComparer of type String.
This interface supports only equality comparisons. Customization of
comparisons for sorting and ordering is provided by the IComparer
generic interface.
We recommend that you derive from the EqualityComparer class
instead of implementing the IEqualityComparer interface, because
the EqualityComparer class tests for equality using the
IEquatable.Equals method instead of the Object.Equals method. This
is consistent with the Contains, IndexOf, LastIndexOf, and Remove
methods of the Dictionary class and other generic
collections.
This issue has been bugging me for a while. Abstractly speaking, regardless of language, there are often situations when you want to have a method like this:
Collection method(Collection c) {
// select some elements from c based on some filter
// and return a new collection
}
Now, Collection is in this case some abstract class (Like say IList in C# or List in Java) with several implementations. I've been wondering what exactly is the right procedure to produce the abstract collection?
Is it ok to create a concrete collection inside the method and return it? Like:
Collection method(Collection c) {
Collection cc = new ConcreteCollection();
// select some elements from c based on some filter
return cc;
}
This of course puts a constraint on the resulting collection and will produce problems in case, for some reason, we want to cast the result of the method to a different concrete collection than the one used inside the method.
Or, use reflection to determine the actual concrete type of c and create an instance of that class:
Collection method(Collection c) {
Collection cc = c.getClass().newInstance();
// select some elements from c based on some filter
return cc;
}
For some reason this does not seem very "elegant" to me. I would greatly appreciate some insight in this matter.
(Speaking for java). The reason you're returning Collection (an interface) rather than a concrete type (such as ArrayList) is that you're telling the user that they shouldn't care about what the actual concrete type being used is. This leaves you free to choose the appropriate type for your library/api.
If you're enforcing a particular concrete class, then you should be returning that concrete class, rather than the interface.
So, they shouldn't be casting your return type to anything else other than Collection. See
When should I return the Interface and when the concrete class?.
In Java, there are actually some good examples of how to do this in the java.util.Collections class. Instead of taking a Collection and returning a Collection, the key methods take two collections, the "src" and the "dest". For example, Look at the signature of the copy method:
public static <T> void copy(List<? super T> dest, List<? extends T> src)
This puts the responsibility of instantiating the destination list on the caller.
I think you could do the same thing when you want to create a method that acts on a src Collection and puts the results into a destination Collection (rather than Lists).
I agree with Matthew Farwell's answer that you probably just want to return the interface and utilize that, but for the times when you really do need to work with a specific implementing class you can do it the same way the Collections class does it.
One approach you could take is to create a Collection implementation that delegates calls through to the original Collection. This defers the potentially expensive operation of filtering a large Collection until you need to explicitly read elements. It also saves memory.
Example
public interface Filter<T> {
boolean include(T t);
}
public class FilterCollection<T> implements Collection<T> {
private final Collection<T> orig;
private final Filter<T> filter;
public FilterCollection(Collection<T> orig, Filter<T> filter) {
this.orig = orig;
this.filter = filter;
}
public int size() {
int sz = 0;
for (T t : orig) {
if (filter.include(t)) {
++sz;
}
}
return sz;
}
public boolean contains(Object o) {
return o instanceof T && filter.include((T) o) && orig.contains(o);
}
public boolean add(T t) {
if (!filter.include(t)) {
throw new IllegalArgumentException("Element lies outside filter bounds.");
}
orig.add(t);
}
}
The caller should assume a given type of Collection is returned.
Instead it should either copy to the desired type or pass the desired type.
e.g.
Set<T> set2 = new HashSet<T>(filter(set));
List<T> list2 = new ArrayList<T>(filter(list));
or
filter(set2, set); // the target collection is passed.
filter(list2, list);
To the question about ConcreteCollection, it is definitely allowable.
To the concern about having a different concrete collection expected, there are a few ways to go around the problem:
Change the return type of the method. Example:
ConcreteCollection method(Collection c){
ConcreteCollection cc=new ConcreteCollection
for(Object x: c){
//do something
}
return cc
}
Make use of polymorphism. Example:
Collection x=method(c)
x.add(new Object) //add is a method defined within the abstract Collection
Use some utilities to cast the type. Example:
LinkedList h=Collections.toLinkedList(method(c))
Hoped my answer helped. ^^
As far as I can understand, you want to know how to make a method that accepts generic list and returns another modified generic list.
So, my advice will be to use an abstract type that implements method to modify its state.
IList<object> list = new List<object>();
list.Add(new object());
list.Remove(obj);
Or as showed above, instantiate a list that implements IList (or the Java equivalent) work with this instance and return the result as a IList
Edit
If you want to filter some item from a list to a new one, generics can help (I don't know if this feature exists in Java).
public IList<T> Filter<T>(IList<T> list)
{
var result = new List<T>();
result.Add(list[0]); // Or whatever filtering method
return result;
}
If you want your method to accept as many different collection types as possible, and you want to be sure that the result is the same implementation type as what you put in, you might want to use a void method which directly modifies the supplied collection. For instance:
import com.google.common.base.Predicate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
public class Testy {
private static <T> void filter(Iterable<T> collection, Predicate<T> filter) {
Iterator<T> iterator = collection.iterator();
while (iterator.hasNext()) {
if (!filter.apply(iterator.next())) { // Condition goes here
iterator.remove();
}
}
}
public static void main(String... args) {
List<String> list = new ArrayList<String>();
list.addAll(Arrays.asList("A", "B", "C", "D"));
filter(list, new Predicate<String>() { // Anonymous filter (predicate)
#Override public boolean apply(String input) {
return input.equals("B");
}
});
System.out.println(list); // Prints ["B"]
}
}
The helper method filter takes an Iterable, the simplest type required for iterating over something. Apply the filter to each element, and if the predicate (filter) returns false, remove that element from the underlying collection with Iterator.remove().
The Predicate<T> interface here comes from Google. You can easily write your own if you don't wish to import it. The only required method is apply(T) which returns a boolean. Either that, or just write your condition directly inside the loop and get rid of the second parameter.
This method is the most efficient if your original collection is mutable and you don't wish to keep any intermediate results.
Another option is to use Google Collections Collections2.filter(Collection<E>, Predicate<E>) which returns a Collection<E> just like in your question. Similarly, the Iterables class will do the same thing, but create lazy iterables where the filters are only applied when actually doing the iterating.