I am trying to write public instance method createParther() that returns an instance of Couple. The method does its job by following these rules: one dancer in the couple must be from aList and the other bList, one dancer in the couple must be male and the other female. Neither dancer in the couple should be partnered already. If it is not possible to create a couple from amongst the unpartnered dancers, then null should be returned. If an instance of Couple is successfully created, both dancers involved in the couple should have their partnered instance variables set to true. I have attempted to list all the aList and bList to together, but then I didn't know to check the requirements as per above. Can anyone demostrate how this could be acheieved? This is not assignment.
public class FoxDancing
{
private List<Couple> coupleList;
private List<Dancer> aList;
private List<Dancer> bList;
public FoxDancing()
{
couplesList = new ArrayList<Parthers>();
aList = new ArrayList<Dancer>();
bList = new ArrayList<Dancer>();
}
public void fieldLists()
{
this.addX("Simon","AList",'m');
this.addX("Jason","AList",'m');
this.addX("Ian","AList",'m');
this.addX("Susan","BList",'f');
this.addX("Helena","BList",'f');
this.addX("Gina","BList",'f');
}
}
It looks like you'd want to have a helper method like this:
Dancer findUnpartnered(List<Dancer> list) {
for (Dancer d : list) {
if (d.isUnpartnered()) {
return d;
}
}
return null;
}
This uses a "foreach loop" for a concise, readable iteration over all Dancer in the List<Dancer>.
Then you can write something like this:
Couple createCouple() {
Dancer a = findUnpartnered(aList);
Dancer b = findUnpartnered(bList);
if (a == null || b == null) {
return null;
} else {
a.setPartnered(true);
b.setPartnered(true);
return new Couple(a, b);
}
}
While this should work, note that findUnpartnered is a O(N) linear search. If the list is of any considerable length, consider having alternative data structures, e.g. a Set<Dancer> that partitions the list into unpartnered and partnered subsets.
On generics invariance
You've written the following:
// snippet from original code
private List<Couple> coupleList;
//...
couplesList = new ArrayList<Parthers>(); // DOES NOT COMPILE!
This will not compile. A List<Partner> (assuming this is what you meant to write) is NOT a List<Couple>. Perhaps you want a new ArrayList<Couple>, or if Partner is a subtype of Couple, then perhaps you want a List<? extends Couple> coupleList.
Related questions
What is the difference between <E extends Number> and <Number>?
See also
Java Tutorials/Generics and Subtyping and More Fun With Wildcards
Angelika Langer's Java Generics FAQ - What is a bounded wildcard?
On enum
You've written the following:
// snippet from original code
this.addX("Simon","AList",'m');
this.addX("Susan","BList",'f');
// potentially "bad" use of String and char constants!
I don't know much about Foxtrot dancing, but if there's a conceptual A-list and B-list , then you may consider using an enum instead of String markers "AList" and "BList". Similarly, if there can only be male or female dancers, then enum would be much better than 'm' and 'f'.
enum FoxTrotter { A, B; }
enum Sex { MALE, FEMALE; }
See also
Java Language Guide/Enums
Related questions
Enumerations: Why? When?
Maybe I don't fully understand your requirements, but since it looks like aList is made up of males and bList females, this could be as simple as shuffling both lists and pairing couples up in a loop until one list is empty.
First write dancer class, complete with all the methods you'll need. Then consider if you want to create an instance of Couple or if you just want to have a each dancer have a reference to their partner. Once you get to this point the rest should start falling into place. :D
Related
I have a java method which has to return both List<ObjectA> and a List<List<String>> for each and every call made to it.
One way I can think of achieving this is by returning Map<String, Object> where string will be key and object will be my lists.
But I think returning a Map is not an elegant way of doing so in my scenario. Any help with this?
With Java 14+, we have the possibility to use Records (JEP 395, openjdk.org). Without knowing anything of the semantics, I will demonstrate the usage with a generic record Pair, but we can of course always find more descriptive names.
We define a generic Pair of generic types T and U:
record Pair<T, U> (T first, U second) {}
And a dummy-implementation of ObjectA:
class ObjectA {
private final String name;
public ObjectA(String name) {
this.name = name;
}
#Override
public String toString() {
return "ObjectA{" +
"name='" + name + '\'' +
'}';
}
}
We can then implement our method like this:
public static Pair<List<ObjectA>, List<List<String>>> foo() {
return new Pair<>(
List.of(new ObjectA("one"), new ObjectA("two")),
List.of(
List.of("three", "four"),
List.of("five", "six"),
List.of("seven", "eight")));
}
And call it like this:
var fooResult = foo();
System.out.println(fooResult.first()); // prints the List<ObjectA>
System.out.println(fooResult.second()); // prints the List<List<String>>
System.out.println(fooResult);
This would produce the following output:
[ObjectA{name='one'}, ObjectA{name='two'}]
[[three, four], [five, six], [seven, eight]]
Pair[first=[ObjectA{name='one'}, ObjectA{name='two'}], second=[[three, four], [five, six], [seven, eight]]]
(Sorry, no Ideone.com demo, Ideone does not support Java 14+, only Java 12)
I guess there's no real universal answer to this question.
One could argue that every time you use Object in Java, it's already somewhat bad since you haven't defined a proper Object containing all of the stuff you need, on the other hand, I really know how much of an annoyance this can be, therefore I try to stick to data structures already available, mainly Maps.
The main problem is that your method(s) calling the method returning an Object need to cast the results anyway - without the knowledge of what this function does, it's hard to give any real advice here.
Therefore my approach would be to look at what exactly are we returning and what these objects actually contain.
I guess the even easier way would be to define a List<List<String>> on your ObjectA and just check of the existence of that list and modify your other method accordingly, if that does make any sense in the context of ObjectA and your methods.
Other than that, I'd probably go with a Map<String,Object> or even Map<?,Object>.
If I understood your question correctly,
you should create a class with two fields List<ObjectA> and List<List<String>>
as a model class. after filling the object with the required data, return it as a return type.
The model class sample :
public class TestModel{
private ObjectA objectA;
private List<List<String>> listOfStrings ;
}
Your method will be :
public TestModel doSomething(....){
//do something
...
//in the end
TestModel testModel = new TestModel();
testModel.setObjectA(objectA);
testModel.setListOfStrings(listOfStrings);
return testModel;
}
I have some base Class A and some (B, C, D, E) different subclasses. All instances of A come from an external data source (database) and I have to infer the actual type at runtime (with marker atttributes stored in the database) and I have no option to change this behaviour.
I end up with a List allAs. At runtime several algorithms have to be executed, that perform on subclasses of A, i.e. I have some algo(List bs), algo(List cs), ... functions and to call them I need to extract all B's, C's or whatever I need from the List.
On the other hand there are algorithms performing on collections of A's.
The following follows:
At some point I need to save references to instances of A's
At some point I need to save references to instances of subclasses
All this data has to be synchronized
The question is, what are best / bad practices to achieve this?
Following solutions come to my mind:
Stick to the List allAs and call as.stream().filter() to extract sublists of given subclasses
each time I have to call a subclass-algorithm
Create a seperate list for each subclass, and combine them all if I need to call an algorithm
that acts on instances of the base class
Do both, but then on update / add / delete actions I need to perform them on each of the lists
(which I need anyways for the second solution)
My intuition tells me that the cleanest way would be to stick to the first principle, but this gets performance critical since I have to handle much data such that filtering the whole collection each time is not viable.
You can avoid duplicated storage if you copy the data into a list or array sorted by the element types. Then, since all elements of the same type are consecutive elements, you can use specific sub-sequences when sub-types are required:
Collection<A> data = externalSource();
// preparation step
class State<T> {
final Class<T> type;
int s, e;
List<?> list;
State(Class<T> c) {
type = c;
}
#SuppressWarnings("unchecked") <U> List<U> as(Class<U> c) {
if(c != type) throw new ClassCastException(c+" != "+type);
return (List<U>)list;
}
}
Map<Class<? extends A>,State<?>> tmp = new HashMap<>();
for(A a: data) tmp.computeIfAbsent(a.getClass(), State::new).s++;
int size = 0;
for(State<?> s: tmp.values()) {
int next = s.s;
s.s = s.e = size;
size += next;
}
A[] all = new A[size];
for(A a: data) all[tmp.get(a.getClass()).e++] = a;
List<A> listOfAll = Arrays.asList(all);
for(State<?> s: tmp.values())
s.list = listOfAll.subList(s.s, s.e);
// now, all lists are available, listOfAll for all As and:
List<B> listOfB = tmp.get(B.class).as(B.class);
List<C> listOfC = tmp.get(C.class).as(C.class);
List<D> listOfD = tmp.get(D.class).as(D.class);
List<E> listOfE = tmp.get(E.class).as(E.class);
System.out.println("B: "+listOfB+",\nC: "+listOfC+",\nD: "+listOfD+",\nE: "+listOfE);
This performs counting sort into the A[] all array, then all lists are created as a view into the array, not having storage of their own. The original collection can be dropped, leaving it subject to garbage collection.
There is one unavoidable unchecked operation, but note that it has an explicit runtime check to ensure safety, assuming the initialization by the code shown above.
This code is easily applicable to a different number of subclasses.
Demo on Ideone
Let's say I have a simple interface:
interface IGroupBy {
String getGroupById();
}
Say I have a list of this:
List<IGroupBy> v = List.of();
But this means that the list has to implement that interface by name.
But what if I am willing to accept any object that had a method that returns a string with that name?
Is there a way to get structural typing in Java using generics somehow?
List<T> v = List.of();
and then tell the Java compiler about T? Something like:
<T hasInterface:IGroupBy>
I suppose one way to get part of the way there is using generics like this:
interface IGroupBy<T> {
T getGroupById();
}
the remaining part is the method name. But that still means you have to reference the same exact interface by name/package.
I am not sure if this is what you are asking for, but I believe that you are talking about java covariance.
Basically, lets say that you have the following class:
class TestClass implements IGroupBy {
private String id;
TestClass(String id) {
this.id = id;
}
#Override
public String getGroupById() {
return id;
}
}
And now, if you have the following list:
List<TestClass> list = List.of(
new TestClass("test1"),
new TestClass("test2")
);
You would like to be able to write something like:
List<IGroupBy> interfaceList = list;
This is supported in java by using a wildcard and can be done like this :
List<? extends IGroupBy> interfaceList = list;
I think the closest thing in Java for what you want to achieve is lambdas and functional interfaces.
That's a good article to read about it: https://www.baeldung.com/java-8-functional-interfaces
List<Function<Integer, Object>> calculators = new ArrayList<>();
calculators.add((number) -> externalCalculator.calculate(number));
calculators.add((number) -> number * number);
calculators.forEach(c -> c.apply(1));
In this example you can see how you can add different logic without any common interfaces to one list(Basically we have Function interface, but I think it's not a problem in this case).
To sum up, Java isn't the best language for such things.
I'm new to java, just about to finish programming fundamentals at uni, so I'd appreciate thorough explanation of any answers. Thanks. Also by the way I am using BlueJ as part of my university training so that might be relevant.
Anyway, here's the problem; I made a text adventure for one of my assignments, and it was very procedural designed, so I decided to revamp it afterwards into a more object oriented program. I think all you need to know about are 4 class'
(some unimportant bits are left out otherwise this would be pages long but if you think they are important let me know);
inventory
static room room;
public inventory(room room)
{
this.room = room;
}
public static room getRoom()
{
return room;
}
room
ArrayList <object> objects = new ArrayList <object>();
public ArrayList getobjects()
{
return objects;
}
object
ArrayList<String> names = new ArrayList<String>();
public ArrayList getNames()
{
return names;
}
textparse (textparse has a textparse method)
public static void textparse(String line)
{
if (line.indexOf(" ") != -1){
int space = line.indexOf(" ");
noun = line.substring(space + 1, line.length()).toLowerCase();
verb = line.substring(0, space).toLowerCase();
}
else
verb = line;
verbparse();
}
Here's the problem; room has an arraylist of objects which are present in it, object has an arraylist of names they can be called by the player. This is my code to attempt to check whether the noun recognized earlier by the textparse class matches any of the objects' names. This is in the textparse class by the way;
public static object nounparse()
{
for (int counter = 0; counter < inventory.getRoom().getobjects().size(); counter++)
{
object current = inventory.getRoom().getobjects().get(counter);
if (current.getNames().contains(noun)){
return current;
}
}
return null;
}
It returns the error 'incompatible types:java.lang.Object cannot be converted to object' referencing this line
object current = inventory.getRoom().getobjects().get(counter);
I'm not sure why it thinks that the output of this is an Object, but due to my limited experience in the field I'm not even sure what an Object is besides a general classifier of a instance of a class. Any help would be appreciated. Thanks!
You are missing a generic parameter. Your getRooms() should return ArrayList<object>, if that's your desired behavior.
Also, you should really rename your object into something else, like Thing and Item, or it may cause confusion, typo, wrong reads (i.e. you may later think you wrote Object not object), etc. All class names are also recommended to be written in Big Camel Case.
Further readings
Java Generics: Java Generics Tutorial at Oracle.com
Java naming convention: (too lazy to find one, see the answer of #DanielWiddis)
The specific source of your error is a downcast. The return type of inventory.getRoom().getobjects().get(counter) appears to be ArrayList. An ArrayList is of type Object in Java, but your lowercase object appears to be a new class definition that is not a superclass or interface for ArrayList. You could refer to it as an ArrayList or List or Collection or Object (note the capitalization), but you are trying to assign it the type object.
For more information on using superclass types, search for tutorials on Java inheritance.
If your object type really was compatible with the ArrayList you could type cast it to the object type, like:
object current = (object) inventory.getRoom().getobjects().get(counter);
However, I seriously doubt that will work in this case and is almost certainly not what you intend; don't play with typecasting unless you know what you're doing. :) I only offer this for you to do more research on typecasting to understand it better.
Also, you need to take a quick look at java coding conventions regarding capitalization of class names and use of camelCase for variable and method names; it'll make your code more readable.
I would like to return 2 different types of class (List<double[]> or List<Double[]) from a single method , as in the below pseudo code. How to achieve this ?
EDITED code and comment : Eclipse does even not allow to compile as this is requested to change the return or data type. I understand YserieScaledCasted will have to be casted manually.
protected List<E[]> getYserieRescaledList(Class<E> c) {
if (Double[].class == c)
return this.YserieScaled;
else if (double[].class == c)
return this.YserieScaledCasted;
}
EDIT2: I found the correct to my problem is simply to overload the method as described here.
You realise you are returning a list of arrays, right? :-)
Short answer:
even though you are passing in Class<E>, you can't use the instanceof operator on a generic type so you can't carry out the if-statement sketched above
the following is ILLEGAL and doesn't compile at each of the two instanceof operators:
class trash {
protected <T> List<T[]> getYserieRescaledList(Class<T> cl) {
List<T[]> result = null;
if (cl instanceof Class<Double>) {
result = ...;
} else if (cl instanceof Class<double>) {
result = ...;
}
return result;
}
}
the reason for this is that generics are a compile-time only construct. All instantiated generic classes are converted to non-generic classes, with types inserted and type casting carried out etc. It makes no sense to ask whether a generic class is instantiated with a particular type at runtime - the generic classes have been swapped for non-generic classes
Instead, cut out the if-statements and simply use the instantiated type to declare variables & arrays, then use your algorithm to populate them and return the result:
class treasure {
protected <T> List<T[]> getYserieRescaledList(Class<T> cl) {
List<T[]> result = null;
// apply general algorithm here to populate the array
// will work identically whether instantiated with Double or double
return result;
}
}
Longer Answer:
Generic classes should represent "template logic" of generalised processing that can be applied with various specific instantiated types.
Good examples are the java Collections, a persistence query framework (such as JPA Criteria API), a financial calculator for different types of investments, or even a SOA service template with standard service "container" infrastructure logic.
In your case, it might be simpler to use pseudo- method overloading (i.e. two methods with slightly different names):
protected List<Double[]> getYserieRescaledList() {
return this.Y;
}
protected List<double[]> getYserieRescaledList2() {
return this.YCasted;
}
Or even better, just stick to double[] as the only case. The compiler will transparently do autobox conversions from double to Double as needed when you extract values into other variables/method parameters.
Just use Double[].class and double[].class. Note that you can't cast a Double[] to a double[] and vice versa, you have to manually copy it. So by extension, you can't cast List<Double[]> to List<double[]> either. Edit: though upon a second glance, it appears this may be the limitation you're trying to correct.
There is some interesting stuff going on here. So your List<double[]> is an List<Array> object where the Array contains primitive doubles.
I would venture to say generics is NOT the right solution here.
I think your best bet is to use the Google Lists library.
something like this:
protected List<Double[]> getYserieRescaledList() {
return this.YseriesScaled;
}
Then, whatever calls your getYseriesRescaledList() can do something like this to get a List<double[]> :
Lists.transform(getYseriesRescaledList(), toPrimitiveDouble());
This will construct a List object in one line of code, using the Function below (from Google Guava):
private Function<Double[], double[]> toPrimitiveDouble(){
return new Function<Double[], double[]>() {
#Override
public double[] apply( Double[] doubles) {
double[] doubleArray = new double[doubles.length];
int i = 0;
for (Double doubleObject : doubles){
doubleArray[i] = doubleObject.doubleValue();
++i;
}
return doubleArray;
}
};
}