Generic method returning ArrayList - java

I am trying to make a program that creates an ArrayList given the type as well as the values that will be put into the ArrayList. The input structure that we have to work with is "I 6 7 5 3 1 -1 2" with the I being the type Integer (or S for String, etc) and the first number (6) being how many values are in the ArrayList. I'm not sure how to instantiate the ArrayList.
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
String type = scan.next();
int length = scan.nextInt();
int counter = 0;
if (type.equals("I")) {
ArrayList<Integer> A = new ArrayList<Integer>;
}
else if (type.equals("S")) {
ArrayList<String> A = new ArrayList<String>;
}
else if (type.equals("D")) {
ArrayList<Double> A = new ArrayList<Double>;
}
else {
System.out.println("Invalid type");
}
while (scan.hasNext() && counter<length) {
String s1 = scan.next();
A.add(s1);
counter += 1;
}
System.out.print(A);
}
//Removes any duplicate values in the arraylist by checking each value after it
public static <E> ArrayList<E> removeDuplicates(ArrayList<E> list) {
ArrayList<E> inArray = list;
for (int i = 0; i<inArray.size(); i++) {
for (int j = i+1; j<inArray.size(); j++) {
if (inArray.get(i) == inArray.get(j)) {
inArray.remove(j);
}
}
}
return inArray;
}
//Shuffles the contents of the array
public static <E> void shuffle(ArrayList<E> list) {
E temp;
int index;
Random random = new Random();
for (int i = list.size()-1; i > 0; i--) {
index = random.nextInt(i + 1);
temp = list.get(index);
list.set(index, list.get(i));
list.set(i, temp);
}
System.out.print(list);
return;
}
//Returns the largest element in the given arraylist
public static <E extends Comparable<E>> E max(ArrayList<E> list) {
E max = Collections.max(list);
System.out.println(max);
return max;
}

I cannot in good conscious give you the answer you want, but rather I'll give you the answer you need.
DON'T DO THAT!
It serves no purpose at all. Datatype erasure at compile time of generics makes the ArrayList<Whatever> act equivalently to ArrayList<?> You cannot ascertain the generic type during runtime unless you type check the elements within the ArrayList
You might as well write this code, it'll give you the same exact results:
public static ArrayList<?> returnProper(String type) {
if(type.length() == 1 && "ISD".contains(type)) {
return new ArrayList();
} else {
System.out.println("Invalid type");
return null;
}
}
THUS, PLEASE DON'T DO THAT

Replace the second E with an "?" and then fix the method to return.
public static <T> ArrayList<?> returnProper(String type) {
if (type.equals("I")) {
return new ArrayList<Integer>();
} else if (type.equals("S")) {
return new ArrayList<String>();
} else if (type.equals("D")) {
return new ArrayList<Double>();
} else {
System.out.println("Invalid type");
}
return null;
}

Related

We can't add a primitive type value to a ArrayList<Integer> right?? Why is this code working ?? (arrayList should only contain only objects right? )

We can't add a primitive type value to a ArrayList right?? Why is this code working ?? (arrayList should only contain only objects right? )
static List<Integer> compareTriplets(List<Integer> a, List<Integer> b) {
int aPoints = 0;
int bPoints =0;
for(int i=0;i<a.size();i++){
if(a.get(i)>b.get(i)){
aPoints++;
} else {
if(a.get(i)<b.get(i)) {
bPoints++;
} else {
if(a.get(i)==b.get(i)){
aPoints = aPoints + 0;
bPoints = bPoints + 0;
}
}
}
}
ArrayList<Integer>points = new ArrayList<>();
points.add(aPoints);
points.add(bPoints);
return points;
}

Java Sorting Algorithms

I have a class called ThreeSorts.java
The aim is to generate a random arraylist of size n - this works.
Then display the array - this works.
Then I have to prove that these sorting algorithms work, however when I pass the random generated array into one of the sorts like SortA(a);
and then display the array it does not get sorted the output is the same:
Generated ArrayList : (153),(209),(167),(117),(243),(67),(0),(148),(39),(188),
SortA ArrayList : (153),(209),(167),(117),(243),(67),(0),(148),(39),(188),
ThreeSorts.java:
import java.util.*;
public class ThreeSorts
{
private static ArrayList<Integer> CopyArray(ArrayList<Integer> a)
{
ArrayList<Integer> resa = new ArrayList<Integer>(a.size());
for(int i=0;i<a.size();++i) resa.add(a.get(i));
return(resa);
}
public static ArrayList<Integer> SortA(ArrayList<Integer> a)
{
ArrayList<Integer> array = CopyArray(a);
int n = a.size(),i;
boolean noswaps = false;
while (noswaps == false)
{
noswaps = true;
for(i=0;i<n-1;++i)
{
if (array.get(i) < array.get(i+1))
{
Integer temp = array.get(i);
array.set(i,array.get(i+1));
array.set(i+1,temp);
noswaps = false;
}
}
}
return(array);
}
public static ArrayList<Integer> SortB(ArrayList<Integer> a)
{
ArrayList<Integer> array = CopyArray(a);
Integer[] zero = new Integer[a.size()];
Integer[] one = new Integer[a.size()];
int i,b;
Integer x,p;
//Change from 8 to 32 for whole integers - will run 4 times slower
for(b=0;b<8;++b)
{
int zc = 0;
int oc = 0;
for(i=0;i<array.size();++i)
{
x = array.get(i);
p = 1 << b;
if ((x & p) == 0)
{
zero[zc++] = array.get(i);
}
else
{
one[oc++] = array.get(i);
}
}
for(i=0;i<oc;++i) array.set(i,one[i]);
for(i=0;i<zc;++i) array.set(i+oc,zero[i]);
}
return(array);
}
public static ArrayList<Integer> SortC(ArrayList<Integer> a)
{
ArrayList<Integer> array = CopyArray(a);
SortC(array,0,array.size()-1);
return(array);
}
public static void SortC(ArrayList<Integer> array,int first,int last)
{
if (first < last)
{
int pivot = PivotList(array,first,last);
SortC(array,first,pivot-1);
SortC(array,pivot+1,last);
}
}
private static void Swap(ArrayList<Integer> array,int a,int b)
{
Integer temp = array.get(a);
array.set(a,array.get(b));
array.set(b,temp);
}
private static int PivotList(ArrayList<Integer> array,int first,int last)
{
Integer PivotValue = array.get(first);
int PivotPoint = first;
for(int index=first+1;index<=last;++index)
{
if (array.get(index) > PivotValue)
{
PivotPoint = PivotPoint+1;
Swap(array,PivotPoint,index);
}
}
Swap(array,first,PivotPoint);
return(PivotPoint);
}
/////////////My Code////////////////
public static ArrayList<Integer> randomArrayList(int n)
{
ArrayList<Integer> list = new ArrayList<>();
Random random = new Random();
for (int i = 0; i < n; i++)
{
list.add(random.nextInt(255));
}
return list;
}
private static void showArray(ArrayList<Integer> a) {
for (Iterator<Integer> iter = a.iterator(); iter.hasNext();)
{
Integer x = (Integer)iter.next();
System.out.print(("("+x + ")"));
System.out.print(",");
//System.out.print(GetAge());
//System.out.print(") ");
}
System.out.println();
}
static void test(int n) {
//int n = 13;
ArrayList<Integer> a = randomArrayList(n);
System.out.println("Generated ArrayList : ");
showArray(a);
System.out.println("SortA ArrayList : ");
SortA(a);
showArray(a);
}
}
Test is called in main like this ThreeSorts.test(10);
Why is it not getting sorted even tho the random array is passed and there are no errors?
In your sample code you are only testing SortA which reads:
ArrayList<Integer> array = CopyArray(a);
...
return(array);
so actually it is taking a copy of your array, sorting it, and then returning you the sorted array.
So when you test it, instead of using:
SortA(a);
you need to use
a = SortA(a);
The type of data your function SortA returns is ArrayList<Integer>, which means it returns an array list of integers. You need to change the line SortA(a); to a = SortA(a);: this way a variable will receive the results of this function's work.
You have to set the returned value, otherwise a will not be sorted in test method. Change the way you call SortA(a) to:
static void test(int n) {
//int n = 13;
ArrayList<Integer> a = randomArrayList(n);
System.out.println("Generated ArrayList : ");
showArray(a);
System.out.println("SortA ArrayList : ");
a = SortA(a);
showArray(a);
}
instead of the method SortA(a); just use Collections.sort(a); inside static block. Like
ArrayList<Integer> a = randomArrayList(n);
System.out.println("Generated ArrayList : ");
showArray(a);
System.out.println("SortA ArrayList : ");
Collections.sort(a);
showArray(a);
Thats it.

Java: <E extends Comparable <E>>

So this program is attempted to take a command line argument like the following:
S 4 1 2 3 4 4
args[0] is the array type
args[1] is the array length
args[2...] are the values in the array
args[length-1] is a key that will be used in a linear search
public class whatTheFoo{
#SuppressWarnings({ "unchecked", "rawtypes" })
public static <E> void main(String[] args) {
for(int i=0;i<args.length;i++)System.out.print(args[i]);
System.out.println();
int arraySize = Integer.parseInt(args[1]);
E[] array = (E[])new Object[arraySize];
E key = null;
if (args[0].matches("I|i")) {
for (int i = 2; i < args.length-1; i++) {
array[i-2]=(E)new Integer(args[i]);
System.out.println(array[i-2]);
}
key = (E) new Integer(args[args.length-1]);
System.out.println("Key is: " + key);
}
...
if(linearSearch(array, key)<0)
System.out.println("Didnt find it");
else
System.out.println("Found it at index: "+(linearSearch(array, key)-1));
}
public static <E> int linearSearch(E[]array,E key) {
int index=-1;
for(int i=0;i<array.length;i++) {
if(array[i].equals(key)){
index = (int) array[i];
}
}
return index;
}
}
This works, but when I change the linearSearch method to:
public static <E extends Comparable<E>> int linearSearch(E[]array,E key)
I get the error message:
The method linearSearch(E[], E extends Comparable<E>) in the type Prog7b is not applicable for the arguments (E[], E)
but if I change main to:
public static <E extends Comparable<E>> void main(String[] args) {
I get:
Exception in thread "main" I412344java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Comparable;
at whatTheFoo.main(whatTheFoo.java:10)
The method has been directed to include in the method:
<E extends Comparable<E>>.
Where am I going wrong? Thanks for reading.
-------------------------------------------------------------------
For those that may be curious, this is the end result of all the help supplied. Thanks again!
public class Prog7b {
// #SuppressWarnings({ "unchecked", "rawtypes" })
public static void main(String[] args) {
if (args[0].matches("I|i")) {
Integer[] array = new Integer[Integer.parseInt(args[1])];
for (int i = 2; i < args.length - 1; i++) {
array[i - 2] = new Integer(args[i]);
}
Integer key = new Integer(args[args.length - 1]);
if (linearSearch(array, key) < 0) {
System.out.println("Didnt find it");
} else
System.out.println("Found it at index: " + (linearSearch(array, key) - 1));
System.out.println("The max of the array is: " + max(array));
print(array);
} else if (args[0].matches("S|s")) {
String[] array = new String[Integer.parseInt(args[1])];
for (int i = 2; i < args.length - 1; i++) {
array[i - 2] = new String(args[i]);
}
String key = new String(args[args.length - 1]);
if (linearSearch(array, key) < 0) {
System.out.println("Didnt find it");
} else
System.out.println("Found it at index: " + (linearSearch(array, key) - 1));
System.out.println("The max of the array is: " + max(array));
print(array);
} else {
Double[] array = new Double[Integer.parseInt(args[1])];
for (int i = 2; i < args.length - 1; i++) {
array[i - 2] = new Double(args[i]);
}
Double key = new Double(args[args.length - 1]);
if (linearSearch(array, key) < 0) {
System.out.println("Didnt find it");
} else
System.out.println("Found it at index: " + (linearSearch(array, key) - 1));
System.out.println("The max of the array is: " + max(array));
print(array);
}
}
public static <E extends Comparable<E>> int linearSearch(E[] array, E key) {
int index = 0;
for (int i = 0; i < array.length; i++) {
index++;
if (array[i].equals(key)) {
return index;
}
}
return -1;
}
public static <E extends Comparable<E>> E max(E[] list) {
E max = list[0];
for (int i = 1; i < list.length; i++) {
if (max.compareTo(list[i]) < 0) {
max = list[i];
}
}
return max;
}
private static <E> void print(E[] list) {
System.out.print("[");
for (int i = 0; i < list.length - 1; i++)
System.out.print(list[i] + ", ");
System.out.print(list[list.length - 1] + "]\n");
}
}
I don't think main is supposed to be generic. (The <E> part in the method declaration declares a type variable, which makes it generic.) If main is really supposed to be generic, then you need to talk to your teacher because they are doing something weird and we can't really guess about it.
Generics are a compile-time only concept. Basically the idea is that you have some code which is actually somewhat agnostic about particular types, but still need some kind of abstract information about it.
For example, suppose we had some method that checks if an object is null:
Object requireNonNull(Object obj) {
if (obj == null) {
throw new NullPointerException();
} else {
return obj;
}
}
This is fine. We can pass any sort of object to the method. (Integer, String, whatever.) But what if we wanted to assign the return value directly?
We want to be able to do this:
String mightBeNull = ...;
String definatelyNotNull = requireNonNull(mightBeNull);
This makes our validation code neater. (Maybe instead of checking for null, our validation is actually about 10 lines long and we don't want to repeat it all the time.)
Well, as it stands, we can't, because we will get a compile-time error for trying to assign an Object to a String.
Generics let us do this, though:
<T> T requireNonNull(T obj) {
if (obj == null) {
throw new NullPointerException();
} else {
return obj;
}
}
The type parameter <T> says that we declare a sort of temporary type. We don't care about what it actually is, but we can say that the method returns whatever we pass to it. Whatever type obj is at the point that we call requireNonNull, the method returns that type to the caller.
So now we can do this:
String s = requireNonNull("");
Integer i = requireNonNull(10);
Float f = requireNonNull(2f);
And so on.
requireNonNull is actually a real method and that is how it works.
The point, though, is that generics let you write very general API which gets called by non-generic code.
For your assignment it looks like you're supposed to write a generic method linearSearch with a bounded type parameter <E extends Comparable<E>> (essentially meaning that whatever array type you pass to linearSearch, it has to be some subtype of Comparable). Then you're probably supposed to pass it different types of arrays in main, like Integer[], String[], etc. Your main method won't be generic. You'll just have an if...else if chain for each type that args[0] requires.

Getting odd/even elements of an arraylist by recursion

I'm making a program where it takes a list of elements in an arraylist and using recursion, gets the even and odd elements. For instance, if it were {1,2,3,4,5,6}. It would return {1,3,5} because they have an even element placement.
I figured out how to do it for even numbers without a hitch, but I can't seem to make it work for odds.
Here is the error:
java.lang.ArrayIndexOutofBoundsException:
-1 (in java.util.ArrayList)
Here is my even code:
public static ArrayList<Integer> even(ArrayList<Integer> tList)
{
ArrayList<Integer> newList = ListMethods.deepClone(tList);
int temp = newList.size();
if (newList.size()<=0)// The list is empty or has one element)
{
return newList;// Return the list as is – no need to reverse!
}
else
{
if(newList.size()%2==0)
temp = newList.remove(newList.size()-2);
newList.remove(newList.size()-1);
newList = ListMethods.even(newList);
if (temp!=0)
newList.add(temp);
}
return newList;
}
Odd Code: (this is where I get the error)
public static ArrayList<Integer> odd(ArrayList<Integer> tList)
{
ArrayList<Integer> newList = ListMethods.deepClone(tList);
int temp = newList.size();
if (newList.size()<=0)// The list is empty or has one element)
{
return newList;// Return the list as is – no need to reverse!
}
else
{
if(newList.size()%2==1)
temp = newList.remove(newList.size()-1);
newList.remove(newList.size()-1);
newList = ListMethods.odd(newList);
if (temp!=0)
newList.add(temp);
}
return newList;
}
Deep Clone:
public static ArrayList<Integer> deepClone(ArrayList<Integer> tList)
{
ArrayList<Integer> list = new ArrayList<Integer>();
for (Integer i : tList)
{
list.add(new Integer(i));
}
return list;
}
My Tester Code:
import java.util.ArrayList;
import java.util.Scanner;
public class ListMethodsRunner
{
public static void main(String[] args)
{
ArrayList<Integer> tempList = ListMethods.makeList(100);
System.out.println("What would you like to do to this ArrayList? Type the number.");
System.out.println("1. Show Even Elements");
System.out.println("2. Show Odd Elements");
System.out.println(" ");
Scanner input = new Scanner(System.in);
int z = input.nextInt();
if(z==1)
tempList = ListMethods.even(tempList);
if(z==2)
tempList = ListMethods.odd(tempList);
if (tempList.size() == 0)
{
System.out.println("The list is empty");
}
else
{
for (Integer i : tempList)
{
System.out.println(i);
}
}
}
}
Nevermind guys, I figured it out by myself.
public static ArrayList<Integer> odd(ArrayList<Integer> tList)
{
ArrayList<Integer> newList = ListMethods.deepClone(tList);
int temp = newList.size();
if (newList.size()<=0)// The list is empty or has one element)
{
return newList;// Return the list as is – no need to reverse!
}
else
{
if(newList.size()%2==0) // I had `1` here instead of `0`
temp = newList.remove(newList.size()-1);
newList.remove(newList.size()-1);
newList = ListMethods.odd(newList);
if (temp!=0)
newList.add(temp);
}
return newList;
I am not sure if the above code will work in case you have odd number of entries May be you can use something like below :
public static ArrayList<Integer> returnList(ArrayList<Integer> tList,boolean flag){
int size=tList.size();
int t;
//print odd positions - flag is true
if(flag){
if(size>0 && size%2==0){
t = tList.remove(size-1);
tList=returnList(tList,flag);
tList.add(t);
}
else if(size%2 == 1){
t = tList.remove(size-1);
tList=returnList(tList,flag);
}
else{
}
System.out.println("Printing.."+tList);
}
else{
}
return tList;
}

How to combine if statements in a loop

I have this class and in the printVotes method I had to do the if statement every time to print each votes. Is there any way to combine both the if statements. Could I print all the names of the candidates and the number of votes they got at the same time?
public class TestCandidate {
public static void main(String[] args)
{
Canidate[] canidate = new Canidate[5];
// create canidate
canidate[0] = new Canidate("John Smith", 5000);
canidate[1] = new Canidate("Mary Miller", 4000);
canidate[2] = new Canidate("Michael Duffy", 6000);
canidate[3] = new Canidate("Tim Robinson", 2500);
canidate[4] = new Canidate("Joe Ashtony", 1800);
printVotes(canidate) ;
}
public static void printVotes(Canidate [] List)
{
double max;
int index;
if (List.length != 0)
{
index = 0;
for (int i = 1; i < List.length; i++)
{
}
System.out.println(List[index]);
}
if (List.length != 0)
{
index = 1;
for (int i = 1; i < List.length; i++)
{
}
System.out.println(List[index]);
return;
}
}
}
If you pass in a List<Candidate> candidates; and assuming that each candidate has a List<Integer> Votes:
List<Integer> votes= new ArrayList<Integer>() ;
for(Candidate c:candidates)
{
votes.add(c.GetVote()) ;
}
for(Integer v:votes)
{
System.out.println(v);
}
You could override the Candidate class's toString() method like so:
public String toString() {
return "Candidate Name: " + this.name + "\nVotes: " + this.votes;
}
Then your printVotes method would look something like this:
public static void printVotes(Candidate[] list) {
for(Candidate c : list) {
System.out.println(c);
}
}
As someone else mentioned, avoid using capital letters in variable names especially in cases where words such as List are used. List is a collection type and can be easily confused.

Categories