I am implementing my own LinkedList class.
For sublist(int a,int b function) method,mycode doesn't work properly.it should return sublist of list according to (a and b indexes)(which i succeed) also after this method if any change is made on sublist also list must be effected(not succeed).for example if i execute
(list.sublist(1,4)).clear :list elements from 1 to 4 should clear also.
My code is:
public List<E> subList(int arg0, int arg1) {
ArrayList<E> ar = new ArrayList<E>();
ListIterator myiter=listIterator(arg0);
int k = arg1 - arg0 + 1;
int i;
for(i = 0; i < k; ++i) {
ar.add((E) myiter.next());
}
List <E> sublist=new GITLinkedList(ar);
return sublist;
}
Why don't you return a class that extends List and overwrites some of the internal methods to trick other classes into thinking its only a subset.
For example, in your sublist method you might do this...
public List<E> subList(int startPosition, int endPosition) {
return new SmallerList(this,startPosition,endPosition);
}
and create a SmallerList class like so...
public class SmallerList extends List {
List parentList = null;
int startPosition = 0;
int endPosition = 0;
public SmallerList(List parentList, int startPosition, int endPosition){
this.parentList = parentList;
this.startPosition = startPosition;
this.endPosition = endPosition;
}
// overwrite some directly to appear smaller
public int size(){
return endPosition-startPosition;
}
// overwrite others to make adjustments to the correct position in the parentList
public void add(int index, Object object){
parentList.add(index+startPosition,object);
}
// overwrite others to only search between startPosition and endPosition
public boolean contains (Object object){
for (int i=startPosition;i<endPosition;i++){
if (parentList.get(i).equals(object)){
return true;
}
}
return false;
}
// etc. for all other methods of List.
}
With this approach, all the methods still act on the underlying parentList, but any queries to SmallerList such as add(), get(), contains(), size(), are all tricked to thinking that they're only working on a smaller List
Related
I am new to java so sorry if this is super basic. I need to make default methods in an interface ISet to allow for the calculation of the union, intersection, and difference of 2 sets created in a class that implements this interface. I know how to calculate all of these but I have no idea how to syntactically do it in the interface since it uses interface objects rather than the data structures in the implementing classes.
The Code:
public interface ISet {
void add(Integer val);
Integer removePos(int pos);
boolean contains(Integer val);
int getSize();
default void union(ISet unionWith) {
//List<Integer>unionSet = new ArrayList<>();
//unionSet.add(unionWith);
//List set = new ArrayList();
//set.addAll(0, unionWith);
//ISet unionSet = this;
// To call in main: this.union(unionWith)
// For my variables it would be mySet.union(mySet2)
//this.getSize();
int size1 = this.getSize();
int size2 = unionWith.getSize();
if(this == unionWith) {
}
//List<Integer> unionList = Arrays.asList(this);
ISet allVals = this.add(Integer val);
for(int i = 0; i < size1 + size2; i++) {
if(!this.contains(Integer.unionWith));
}
}
default void intersect(ISet intWith) {
}
default void difference(ISet diffWith) {
}
}
Sorry for the graveyard I'm just trying every thing I can. Pretty much none of this works except for the size stuff. I know that I'm supposed to use all of the other methods above but I have no idea how to use them in this scenario.
I usually try and figure out things like this by myself but after 3 hours of not being able to union two sets I've realized that I just need to get more informed on how java and interfaces work.
I'll really appreciate any help you guys have to offer!
Maybe you need a methed : Integer get(int pos);
public interface ISet {
void add(Integer val);
Integer get(int pos);
Integer removePos(int pos);
boolean contains(Integer val);
int getSize();
default void union(ISet unionWith) {
for (int i = 0; i < unionWith.getSize(); i++) {
this.add(unionWith.get(i));
}
}
default void intersect(ISet intWith) {
for (int i = getSize() - 1; i >= 0; i--) {
Integer value = get(i);
if (!intWith.contains(value)) {
removePos(i);
}
}
}
default void difference(ISet diffWith) {
for (int i = getSize() - 1; i >= 0; i--) {
Integer value = get(i);
if (diffWith.contains(value)) {
removePos(i);
}
}
}
}
That's basically my first touch with Java generic types and I can't figure out what is wrong with the following piece of code.
I have a helper class Helper with a static function inRange usng generic type that should return the list of objects from an input list that are in certain range around object at index index (I haven't tested it yet, it's not an issue here if it works correctly or not):
public class Helper {
public static <T> List<T> inRange(List<T> list, int index, int range) {
List<T> res = new ArrayList<T>();
int N = list.size();
assert(index < N);
if (N == 0)
return res;
int i, j;
/* right range */
i = (index + 1) % N;
j = 0;
while (i != index && j < range) {
res.add(list.get(i));
i = (i + 1) % N;
j++;
}
/* left range */
i = (N + index - 1) % N;
j = 0;
while (i != index && j < range && !res.contains(list.get(i))) {
res.add(lista.get(i));
i = (N + i - 1) % N;
j++;
}
return res;
}
}
Then I want to use it in a class:
import java.util.ArrayList;
public class StrategyA extends StrategyB {
public Decision makeDecision(GameView gameView, Action action, View playerView) {
int pos = gameView.activePlayersViews().indexOf(playerView);
assert(pos != -1);
ArrayList<View> inRange = Helper.inRange(gameView.activePlayersViews(), pos,
playerView.range());
// todo ...
return new Decision(Decision.KindOfDecision.DO_NOTHING, 0);
}
}
where gameView.activePlayersView() is of type ArrayList<View>.
Then from my IDE (IntelliJ IDEA) on the line calling inRange(..) I get
Error:(8, 56) java: incompatible types: no instance(s) of type variable(s) T exist so that java.util.List<T> conforms to java.util.ArrayList<View>
Even I change generic type T directly to View I still get this error
ArrayList is an implementation of List interface.
So all ArrayList instances are List instances but all List instances are not necessarily ArrayList.
So when you call this method :
public static <T> List<T> inRange(List<T> list, int index, int range) {
you cannot assign its result to an ArrayList as you are doing :
ArrayList<View> inRange = Helper.inRange(...);
Go on to program by interface and use List in both sides :
List<View> inRange = Helper.inRange(...);
Minimize your example like (using Integer of the templated List type):
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
List<Integer> list = new ArrayList<Integer>();
ArrayList<Integer> inRange = Helper.inRange(list, 0,1);
}
}
class Helper {
public static <T> List<T> inRange(List<T> list, int index, int range) {
List<T> res = new ArrayList<T>();
return res;
}
}
Then even if you put template types out of the picture:
ArrayList inRange = Helper.inRange(list, 0,1);
public static List inRange(List list, int index, int range) { ... }
you see that while the helper static method returns a List, you are trying to assign it to an ArrayList, and that's your problem, as ArrayList is a concrete implementation of List, but you cannot assign a reference to a generic List to a concrete implementation of ArrayList
Just change to:
List<View> inRange = Helper.inRange(gameView.activePlayersViews(), pos,
playerView.range());
and you are good to go: https://ideone.com/MXZxqz
It happens, because inRange() returns type List<T>. You can store result in reference with type List or any supertype.
Try to use this code:
List<View> inRange = Helper.inRange(gameView.activePlayersView(), pos,
playerView.range());
Try to do:
List<View> inRange = Helper.inRange(gameView.activePlayersView(), pos,
playerView.range());
And check this:
res.add(lista.get(i));
there is no lista in this class
You need to cast the type ArrayList to be List
ArrayList<View> inRange = Helper.inRange((List<View>) gameView.activePlayersViews(), pos,
playerView.range());
I don't understand why I get ClassCastException on below code in line:
for(int i = 0; i < k.t.length; i++)
So problem is that in method addElement I make replacing of array elements by objects with type T. In my opinion in array should be objects with type T. And compiler doesn't protest for that.
But in run-time JVM cannot cast despite in array is really objects with type T (in case below String), why JVM cannot use polymorphism?
But when I change the T[] t; to Object[] t;
and remove cast in constructor it run correctly without any errors, why?
public class MyCollection<T> {
T[] t;
MyCollection( int size){
t = (T[]) new Object[size];
}
boolean addElement(T e, int i){
if(i < t.length){
t[i] = e;
return true;
}
return false;
}
public static void main(String[] ss){
MyCollection<String> k = new MyCollection<String>(3);
k.addElement("a",0);
k.addElement("b",1);
k.addElement("c",2);
for(int i = 0; i < k.t.length; i++)
System.out.println(k.t[i]);
//for(String s : (String[])k.t)
// System.out.println(s);
}
}
The problem is that you're casting Object[] to T[], and then you're exposing the underlying array. The only reason this works altogether is because the type erasure of T is Object. But since in our case T is being interpreted as String, when we access the array externally, we're trying to cast it to String[], which is incorrect. In order to avoid this issue, you should make the array private and provide accessor methods to retrieve elements. By doing that, you only cast individual elements to their correct type without making assumptions about the underlying array.
public class MyCollection<T> {
private T[] t;
MyCollection( int size){
t = (T[]) new Object[size];
}
boolean addElement(T e, int i){
if(i < t.length){
t[i] = e;
return true;
}
return false;
}
T getElement(int index) {
return t[index];
}
int getLength() {
return t.length;
}
public static void main(String[] ss){
MyCollection<String> k = new MyCollection<String>(3);
k.addElement("a",0);
k.addElement("b",1);
k.addElement("c",2);
for(int i = 0; i < k.getLength(); i++)
System.out.println(k.getElement(i));
//for(String s : (String[])k.t)
// System.out.println(s);
}
}
Note that Java's Collection interface demonstrates the same behavior. Collection.toArray() returns Object[] regardless of the type of E. The only available workaround is Collection.toArray(T[]), where you're forced to pass an array with a fixed type, which can then be either be populated or copied.
Check again the line of the problem. In my opinion the exception will be thrown because of:
for(String s : (String[])k.t)
You`re trying to cast to String[] here, while the array is defined as Object[]:
t = (T[]) new Object[size];
you can Create a new instance of array using the reflection to avoid ClassCastException
example:
import java.lang.reflect.Array;
public class MyCollection<T> {
T[] t;
MyCollection(Class<T> clazz, int size) {
t = (T[]) Array.newInstance(clazz, size);
}
boolean addElement(T e, int i) {
if (i < t.length - 1) {
t[i] = e;
return true;
}
return false;
}
public static void main(String[] ss) {
MyCollection<String> k = new MyCollection<String>(String.class, 3);
k.addElement("a", 0);
k.addElement("b", 1);
k.addElement("c", 2);
for (int i = 0; i < k.t.length; i++)
System.out.println(k.t[0]);
}
}
I have about 10+ classes, and each one has a LUMP_INDEX and SIZE static constant.
I want an array of each of these classes, where the size of the array is calculated using those two constants.
At the moment i have a function for each class to create the array, something along the lines of:
private Plane[] readPlanes()
{
int count = header.lumps[Plane.LUMP_INDEX].filelen / Plane.SIZE;
Plane[] planes = new Plane[count];
for(int i = 0; i < count; i++)
planes[i] = new Plane();
return planes;
}
private Node[] readNodes()
{
int count = header.lumps[Node.LUMP_INDEX].filelen / Node.SIZE;
Node[] nodes = new Node[count];
for(int i = 0; i < count; i++)
nodes[i] = new Node();
return nodes;
}
private Leaf[] readLeaves()
{
int count = header.lumps[Leaf.LUMP_INDEX].filelen / Leaf.SIZE;
Leaf[] leaves = new Leaf[count];
for(int i = 0; i < count; i++)
leaves[i] = new Leaf();
return leaves;
}
etc.
There are 10 of these functions, and the only differences is the class type, so as you can see, there's a ton of duplication.
Does any one have any ideas on how to avoid this duplication?
Thanks.
(I asked a similar question before, but i guess the way i asked it was a bit off)
Use Java generics. That way, you can just write one generic method and specify a type parameter each time you use it.
Bala's solution is close. You can't access constants from the generic type though, so I'd create a getCount() (or whatever you want to name it) and have each subtype implement it with the appropriate constants.
interface LumpySize<L extends LumpySize> {
int getCount(); // subtypes return the appropriate header.lumps[Plane.LUMP_INDEX].filelen / Plane.SIZE;
T[] initializeArray();
abstract <T extends LumpySize> static class Base implements LumpySize<T> {
protected T[] initializeArray(Class<T> cls) {
int count = getCount();
T[] lumps = (T[]) Array.newInstance(cls, count);
for(int i = 0; i < count; i++) {
try {
lumps[i] = cls.newInstance();
} catch (Exception e) { // obviously this isn't good practice.
throw new RuntimeException(e);
}
}
return lumps;
}
}
}
class Plane extends LumpySize.Base<Plane> {
public int getCount() {
return header.lumps[Plane.LUMP_INDEX].filelen / Plane.SIZE; // assuming header is available somewhere
}
public Plane[] initializeArray() { return initializeArray(Plane.class); }
}
Okey doke ... I've tested this to make sure, and I believe it does what you're looking for.
You need an interface:
public interface MyInterface
{
public int getSize();
public int getLumpIndex();
}
Your classes implement that interface:
public class Plane implements MyInterface
{
...
public int getSize()
{
return SIZE;
}
public int getLumpIndex()
{
return LUMP_INDEX;
}
}
In the class that header is an instance of, you have ...
public <E extends MyInterface> E[]
getArray(Class<E> c, MyInterface foo)
{
int count = lumps[foo.getLumpIndex()].filelen / foo.getSize();
E[] myArray = (E[]) Array.newInstance(c, count);
for(int i = 0; i < count; i++)
myArray[i] = c.newInstance();
return myArray;
}
You could call it from say, your Plane class as:
Plane[] p = header.getArray(Plane.class, this);
I think? :) Can someone look at this and see if I'm off?
(EDIT: Becasue I've tested it now - That works)
On an additional note, you could eliminate the getters in each class by making getArray() take the size and index as arguments:
public <E extends MyInterface> E[]
getArray(Class<E> c, int size, int index)
{
int count = lumps[index].filelen / size;
E[] myArray = (E[]) Array.newInstance(c, count);
for(int i = 0; i < count; i++)
myArray[i] = c.newInstance();
return myArray;
}
And call it as:
Plane p[] = header.getArray(Plane.class, SIZE, LUMP_INDEX);
from inside your classes. The interface just becomes empty to provide the generic type and you don't have to define the getter methods.
OR (last edit I promise, but this does give you choices and explains a bit about generics)
Ditch the interface. What this removes is some sanity checking because the method doesn't care what type of object you give it:
public <E> E[]
getArray(Class<E> c, int size, int index)
{
...
Now you don't have to define the interface or implement it, you just call:
Plane p[] = header.getArray(Plane.class, SIZE, LUMP_INDEX);
Use generics, but you'll need to pass in some sort of factory object to construct instances to put in your collection, eg:
public class MyClass {
public <E> E[] getArray(IObjectFactory builder, int index, int size){
ArrayList<E> arrayList = new ArrayList<E>();
int count = header.lumps[index].filelen / size;//wasn'tsure where header was coming from...
for(int i = 0; i< count; i++){
E newInstance = builder.getNewInstance();
arrayList.add(newInstance);
}
return (E[]) arrayList.toArray();
}
}
interface IObjectFactory {
<E> E getNewInstance();
}
What's the shortest way to get an Iterator over a range of Integers in Java? In other words, implement the following:
/**
* Returns an Iterator over the integers from first to first+count.
*/
Iterator<Integer> iterator(Integer first, Integer count);
Something like
(first..first+count).iterator()
This implementation does not have a memory footprint.
/**
* #param begin inclusive
* #param end exclusive
* #return list of integers from begin to end
*/
public static List<Integer> range(final int begin, final int end) {
return new AbstractList<Integer>() {
#Override
public Integer get(int index) {
return begin + index;
}
#Override
public int size() {
return end - begin;
}
};
}
Edit:
In Java 8 and later you can simply say:
IntStream.range(begin, end).iterator() // returns PrimitiveIterator.OfInt
or if you need the boxed version:
IntStream.range(begin, end).boxed().iterator() // returns Iterator<Integer>
Untested. Mapping that onto "min, count" is left as an exercise for the reader.
public class IntRangeIterator implements Iterator<Integer> {
private int nextValue;
private final int max;
public IntRangeIterator(int min, int max) {
if (min > max) {
throw new IllegalArgumentException("min must be <= max");
}
this.nextValue = min;
this.max = max;
}
public boolean hasNext() {
return nextValue <= max;
}
public Integer next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return Integer.valueOf(nextValue++);
}
public void remove() {
throw new UnsupportedOperationException();
}
}
If you actually want the shortest amount of code, then Bombe's answer is fine. However, it sucks memory for no good reason. If you want to implement it yourself, it would be something like:
import java.util.*;
public class IntegerRange implements Iterator<Integer>
{
private final int start;
private final int count;
private int position = -1;
public IntegerRange(int start, int count)
{
this.start = start;
this.count = count;
}
public boolean hasNext()
{
return position+1 < count;
}
public Integer next()
{
if (position+1 >= count)
{
throw new NoSuchElementException();
}
position++;
return start + position;
}
public void remove()
{
throw new UnsupportedOperationException();
}
}
An example using the guava framework. Note that this will not materialize the set (although you have to read the ContiguousSet implementation to verify that).
import com.google.common.collect.ContiguousSet;
import com.google.common.collect.DiscreteDomain;
import com.google.common.collect.DiscreteDomains;
class RangeIterator {
public Iterator<Integer> range(int start, int length) {
assert length > 0;
Range<Integer> dim_range = Ranges.closedOpen(start, start + length);
DiscreteDomain<Integer> ints = DiscreteDomains.integers();
ContiguousSet<Integer> dim = dim_range.asSet(ints);
return dim.iterator();
}
}
A sample using stream API in java 8:
int first = 0;
int count = 10;
Iterator<Integer> it = IntStream.range(first, first + count).iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
Without iterator, it could be:
int first = 0;
int count = 10;
IntStream.range(first, first + count).forEach(i -> System.out.println(i));
Straight-forward implementation of your homework:
List<Integer> ints = new ArrayList<Integer>();
for (int i = 0; i < count; i++) {
ints.add(first + i);
}
It's generally considered good style to pass around Collection and friends instead of Iterator (see this FAQ entry), so I'd recommend something like
public final class IntegerRange implements Set<Integer> {
final LinkedHashSet<Integer> backingList;
public IntegerRange(final int start, final int count) {
backingList = new LinkedHashSet(count, 1.0f);
for (int i=0; i < count; i++) {
backingList.set(i, start + i);
}
}
/** Insert a bunch of delegation methods here */
}
and then just use .iterator() when you need to pass an Iterator to whatever framework you're using.
UPDATE: Obviously, this code isn't lazy. If you can't afford the extra memory overhead of storing (potentially) 2^32-1 Integers, you should use a different solution. Also, nothing about the type guarantees the range will be sorted (even though it is, based on the implementation). If you need to guarantee sorting, you could look into implementing SortedSet and backing it with a TreeSet, but it will take longer to build the range. Honestly, if you are that concerned with getting the details right, it might be worth your effort to look for a library. Tapestry has an internal version, for instance.