How to create a general list that can take two different unrelated types?

I need to define a List and have two types of possible values

  • Line
  • User Defined Class

How to create a list that is type safe because it accepts only these two types?

I want to avoid using raw List.

+5
source share
10 answers

I want to define a List that can accept objects of only two types (above defined), any attempt to add other than these two types should ask me for "ERPOR ERROR"

This does what you ask for (with a runtime error):

public class MyList extends ArrayList<Object> {

    public MyList() {
        super();
    }

    public MyList(int initialSize) {
        super(initialSize);
    }

    @Override
    public void add(Object obj) {
        if ((obj instanceof String) || (obj instanceof SomeType)) {
            add(obj);
        } else {
            throw new IllegalArgumentException("not a String or SomeType");
        }
    }

    public void add(String s) {
        super.add(s);
    }

    public void add(SomeType s) {
        super.add(s);
    }
}

Java , , ( ) List. , List, add .. "" , add(T) . , ( Java), , .

+2

, , "", " " ( , , "verbose, " ).

, , . :

:

class Holder {
  private String foo;
  private UserClass bar;
  boolean isString;
  boolean initialized=false;
  Holder (String str) { foo = str; isString=true; }
  Holder (UserClass bar) { this.bar = bar; isString=false; }
  String getStringVal () { 
      if (! initialized) throw new IllegalStateException ("not initialized yet");
      if (! isString) throw new IllegalStateException ("contents not string");
      return foo;
  }
  // with a similar method for getUserClassVal()
...
}

enum , isString - .

, , :

   List samsList = new ArrayList()

, , :

   samsList.add (new Holder(stringVal));
   samsList.add (new Holder(userClassVal));

: (holder.isString()), , . , foreach :

   for (Holder holder: samsList) {
      if (holder.isString())
         doYourStringProcessing (holder.getStringVal());
      else
         doYourUserClassProcessing (holder.getUserClassVal());
   }

, , , , .

, , , , , / -. , , , , , , " ?".

: , , , . , ( " X Y" " X Y, Z" ).

, , , /.

+8

String Object , String , Object. , List<Object> - , .

- . , , , , .

+7

- "". , . . .

:

final List<Either<Integer, String>> list = new ArrayList<>();

list.add(Either.left(1234));
list.add(Either.right("hello"));

for (final Either<Integer, String> i : list) {
    if (i.isLeft()) {
        System.out.println(i.left());
    } else {
        System.out.println(i.right());
    }
}

:

package com.stackoverflow.q1351335;

public interface Either<L, R> {

    boolean isLeft();

    L left();

    R right();

    static <L, R> Either<L, R> left(final L value) {
        return new EitherLeft<>(value);
    }

    static <L, R> Either<L, R> right(final R value) {
        return new EitherRight<>(value);
    }
}

package com.stackoverflow.q1351335;

import java.util.Objects;

public final class EitherLeft<L, R> implements Either<L, R> {
    private final L value;
    public boolean isLeft() {
        return true;
    }
    public L left() {
        return value;
    }
    public R right() {
        throw new IllegalStateException("Cannot get right value from an EitherLeft");
    }
    public EitherLeft(final L value) {
        super();
        this.value = value;
    }
    @Override
    public boolean equals(final Object obj) {
        if (obj instanceof EitherLeft) {
            Objects.equals(this.value, ((EitherLeft) obj).value);
        }
        return false;
    }
    @Override
    public int hashCode() {
        return Objects.hashCode(value);
    }
    @Override
    public String toString() {
        return "EitherLeft[" + Objects.toString(value) + "]";
    }
}

package com.stackoverflow.q1351335;

import java.util.Objects;

public final class EitherRight<L, R> implements Either<L, R> {
    private final R value;
    public boolean isLeft() {
        return false;
    }
    public L left() {
        throw new IllegalStateException("Cannot get left value from an EitherRight");
    }
    public R right() { return value; }
    public EitherRight(final R value) {
        super();
        this.value = value;
    }
    @Override
    public boolean equals(final Object obj) {
        if (obj instanceof EitherRight) {
            Objects.equals(this.value, ((EitherRight) obj).value);
        }
        return false;
    }
    @Override
    public int hashCode() {
        return Objects.hashCode(value);
    }
    @Override
    public String toString() {
        return "EitherRight[" + Objects.toString(value) + "]";
    }
}

Either:

// Illustration of usage: 
myEither.match(
    leftValue -> {
        // Do stuff with left
    }, 
    rightValue -> {
        // Do stuff with right
    });

, EitherRight EitherLeft. , ( FP) .

+2

" ", , .

, String final, String.

String , String, String , List<? extends String>:

// Not possible.
List<? extends String> list = new ArrayList<? extends String>;
list.add("A string");
list.add(new UserDefinedSubclassOfString());   // There can be no such class.

, , List s, , :

class MyList {

    List<String> strings;
    List<UserDefined> objects;

    public void add(String s) {
        strings.add(s);
    }

    public void add(UserDefined o) {
        objects.add(o);
    }

    // And, so on.
}

, List, E. , Object ? (.. List<Object> List<?>, ), , , Java Object .

, , MyList. get, String UserDefined. Object.

, , . , getString getUserDefined. , List, E get.

kdgregory , , , , , , , .

, , Lesson: Generics Java .

+1

kdgregory, , , . , , List<String> List<Whatever>. , List<SomeContainer>, String . , , , class Blah<T> class Blah, T String, UserClass - .

0

, , , MyType, String , , .

, . - , . , .

0

, " "? , . , . ?

- ? , String , - ? BaseUserDefinedClass , :

List<? extends BaseUserDefinedClass> = new ArrayList<DerivedFromBaseUserDefinedClass>();
0

, ...

, :

List<String> stringList = new ArrayList<String>();
// Add String
stringList.add("myString");
// add YourObject
YourObject obj = new YourObject(...);
stringList.add(obj.toString());
// ...
for(String s : stringList) {
    System.out.println(s);
}

YourObject:

List<YourObject> objList = new ArrayList<YourObject>();
// Add String 
objList.add(new YourObjectAdapter("myString"));
// add YourObject
YourObject obj = new YourObject(...);
objList.add(obj)
// ...
for (YourObject y : objList) {
    System.out.println(y.toString());
    // Assuming YourObject defines the "doSomething() method"
    y.doSomething();
}
// ...
class YourObjectAdapter extends YourObject {
    private String wrappedString;
    public YourObjectAdapter(String s) {
        this.wrappedString = s;
    }
    @Override
    public void toString() {
        return wrappedString();
    }
    @Override
    public void doSomething() {
      // provide some default implementation...
    }
}
0

. Java, 29: . , .

, List List<Object>, String ? , ?

, - :

import java.util.*;

public class HetContainer {
  Set<Class<?>> allowableClasses;

  List<Object> items;

  public HetContainer(List<Class<?>> allowableClasses) {
    this.allowableClasses = new HashSet<Class<?>>(allowableClasses);
    items = new ArrayList<Object>();
  }

  public void add(Object o) {
    if (allowableClasses.contains(o.getClass())) {
      items.add(o);
    } else {
      throw new IllegalArgumentException("Object of type " + o.getClass() + " is not allowed.");
    }
  }

  public Object get(int i) {
    return items.get(i);
  }

  public static void main(String[] args) {
    List<Class<?>> classes = new ArrayList<Class<?>>();
    classes.add(String.class);
    classes.add(Integer.class);
    HetContainer h = new HetContainer(classes);
    h.add("hello");
    h.add(new Integer(5));
    try {
      h.add(new Double(5.0));
    } catch (IllegalArgumentException e) {
      System.out.println(e);
    }
  }
}

, , . , , ... ? List<Integer>.class List<Double>.class. , - ""... List s. , raw List HetContainer, List. " Java", java .

0

All Articles