Refactoring a nested loop - java

I have the following code which I use a lot of times in the class.
for (int i = 0; i < someList.size(); i++) {
for (int j = 0; j < someList.size(); j++) {
if (i != j) {
someList.get(i).sendMessageTo(someList.get(j))); //variable action
}
}
}
The purpose of the loop is to make each element in the List to send a message (or perform another action) to every element in the list except itself.
Is there any way I can create a helper method so I don't have to repeat the loop code.
Edit:
I need just one helper method to take care of the for loop and the if algorithm. I will supply the List and the whatever action I need to use. It should work for all.
I want to be able to state the variable action and call the helper method.
Thanks.

You could do something like (I don't know what type is in your List, I called it Element):
public interface ApplySomeAction
{
public apply(Element e1, Element e2);
}
...
public void applyActionToAllElements(ApplySomeAction action)
{
for (int i = 0; i < someList.size(); i++) {
for (int j = 0; j < someList.size(); j++) {
if (i != j) {
action.apply(someList.get(i), someList.get(j));
}
}
}
}
later call it with:
applyActionToAllElements(new ApplySomeAction() {
public apply(Element e1, Element e2)
{
e1.sendMessageTo(e2));
}
};
Could make another interface+method with just one element if you often do an action with just one of those elements.

You could maybe get rid of one of the loops by doing it this way:
for (int i = 0; i < someList.size() - 1; i++) {
someList.get(i).sendMessageTo(someList.get(i + 1))); //variable action
}
And use #NESPowerGlove's solution to abstract the method that's called.

I'd make me an Iterable
/**
* Returns all pairs of the list except those where i == j.
* #param <T>
*/
public class AllPairs<T> implements Iterable<Pair<T, T>> {
// The list.
private final List<T> list;
public AllPairs(List<T> list) {
this.list = list;
}
#Override
public Iterator<Pair<T, T>> iterator() {
return new PairIterator();
}
private class PairIterator implements Iterator<Pair<T, T>> {
// The indexes.
int i = 0;
int j = 0;
// The next to return.
Pair<T, T> next = null;
// Easier to read.
int size = list.size();
#Override
public boolean hasNext() {
while (next == null && (i < size || j < size)) {
// Step j.
j += 1;
// Wrap j.
if (j >= size && i < size) {
j = 0;
i += 1;
}
if (i < size && j < size && j != i) {
// Grab it.
next = new Pair<>(list.get(i), list.get(j));
}
}
return next != null;
}
#Override
public Pair<T, T> next() {
Pair<T, T> it = next;
next = null;
return it;
}
}
}
/**
* A simple Pair
*/
public static class Pair<P, Q> {
public final P p;
public final Q q;
public Pair(P p, Q q) {
this.p = p;
this.q = q;
}
}
public void test() {
System.out.println("Hello");
List<Integer> l = Arrays.asList(0, 1, 2, 3);
for (Pair<Integer, Integer> p : new AllPairs<>(l)) {
System.out.println("[" + p.p + "," + p.q + "]");
}
}
Then define an interaction mechanism - this would be almost trivial using Lambdas:
// Objects that can interact with each other.
public interface Interacts<T extends Interacts<T>> {
public void interact(T with);
}
public static <T extends Interacts<T>> void interactAllPairs(List<T> l) {
// Interact all pairs.
for (Pair<T, T> p : new AllPairs<>(l)) {
p.p.interact(p.q);
}
}
Then you can make your message objects interact - here's a simple example:
// Interact by sending a message.
public class Messenger implements Interacts<Messenger> {
private final int me;
public Messenger(int me) {
this.me = me;
}
#Override
public void interact(Messenger with) {
sendMessage(with);
}
public void sendMessage(Messenger to) {
System.out.println(this + "->" + to);
}
#Override
public String toString() {
return Integer.toString(me);
}
}
Testing now looks like:
public void test() {
// Meassage list.
List<Messenger> messages = new ArrayList<>();
for (int i = 0; i < 4; i++) {
messages.add(new Messenger(i));
}
interactAllPairs(messages);
}
giving your required output:
0->1
0->2
0->3
1->0
1->2
1->3
2->0
2->1
2->3
3->0
3->1
3->2

Related

Generic Linear List based on Arrays

I'm trying to write a Linear List based on arrays, but make the list be able to store any value by using Java Generics. This way I can create other programs that utilize it, but pass in different data types. I'm not entirely sure how to do this, any help would be appreciated.
I guess Im struggling trying to set it up and create the functions. The generic type really messes me up.
For example, trying to add a removeFirst() function, I cant use a loop like this:
for (int i = 0; i < n - 1; i++)
newList[i] = newList[i + 1];
— as it says The type of the expression must be an array type but it resolved to ArrayList.
Fair warning, I'm still learning data structures. This is what I have so far:
import java.util.ArrayList;
public class LinearList<T> {
private static int SIZE = 10;
private int n = 0;
private final ArrayList<T> newList = new ArrayList<T>(SIZE);
private T t;
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
public void add(T value, int position) {
newList.add(position, value);
n++;
}
public void addFirst(T value) {
newList.add(0, value);
n++;
}
public void removeLast() {
T value = null;
for (int i = 0; i < newList.size(); i++)
value = newList.get(i);
newList.remove(value);
n--;
}
public void removeFirst() {
newList.remove(0);
n--;
}
public T first() {
return newList.get(0);
}
public T last() {
int value = 0;
for (int i = 0; i < newList.size() - 1; i++)
value++;
return newList.get(value);
}
public int count() {
return n;
}
public boolean isFull() {
return (n >= SIZE);
}
public boolean isEmpty() {
return (n <= 0);
}
//part 4
public void Grow() {
int grow = SIZE / 2;
SIZE = SIZE + grow;
}
public void Shrink() {
int grow = SIZE / 2;
SIZE = SIZE - grow;
}
public String toString() {
String outStr = "" + newList;
return outStr;
}
}
A good start would be to make it non-generic with a class you are comfortable with, such as an Integer.
Once you have it set up, you can then make it generic by adding <T> to the class name, then replacing all references of Integer with T.
public class MyArray{ becomes public class MyArray<T>{
public Integer add(Integer value){ becomes public T add(T value){
See What are Generics in Java? for more help

Create all Combinations Java

I want to create all combinations with two states(1 and 0).
If i do this with two for-loops, this works. But when I use a self-calling function it doesnt. Does anybody can tell me why, please ?
For-Loops :
public class Counter {
public Counter() {
loop(iter);
for (int i=0; i < 2; i++) {
for (int i2=0; i2 < 2; i2++) {
System.out.println(Integer.toString(i)+Integer.toString(i2));
}
}
}
public static void main(String args[]){
new Counter();
}
}
Self-Calling Function :
class Stringhelper {
public Stringhelper() {
}
public String getstring(String string,int beginning,int ending) {
if (string.length() != 0) {
String newstring="";
for (int iter=Math.abs(beginning); iter < ending && iter < string.length(); iter=iter+1) {
newstring=newstring+Character.toString(string.charAt(iter));
}
return newstring;
}
else {
return "";
}
}
}
public class Counter {
public String abil="";
public int iter=1;
public Stringhelper shelper=new Stringhelper();
public void loop(int iter) {
for (int i=0; i < 2; i++) {
abil=abil+Integer.toString(i);
if (iter==0) {
System.out.println(abil);
abil=shelper.getstring(abil,0,abil.length()-1);
}
else {
loop(iter-1);
}
}
}
public Counter() {
loop(iter);
}
public static void main(String args[]){
new Counter();
}
}
And using the self-calling Function the output is 00,01,010,011 instead of 00,01,10,11
Explaining your code here (ignore abil for now):
public void loop(int iter) {
for (int i=0; i < 2; i++) {
abil=abil+Integer.toString(i);
if (iter==0) {
System.out.println(abil);
abil=shelper.getstring(abil,0,abil.length()-1);
}
else {
loop(iter-1);
}
}
}
When iter is 0 it will print it
In the next iteration, when it is not equal to 0, another loop is created, added to the stack, where it starts again from 0, and prints abil's new stack value.
When you create a new stack it recreates all the variables in temporary storage until the code exits. In this case it keeps creating stacks and never exits. In order to exit a stack, use return.
In summary, you need to learn more about how stacks and recursion work in order to fix your problem.
public void loop(int iter) {
for (int i=0; i < 2; i++) {
if (i==1) {
abil=shelper.getstring(abil,0,iter);
}
abil=abil+Integer.toString(i);
if (iter==4) {
System.out.println(abil);
}
else {
loop(iter+1);
}
}
}
this did the trick

My function seems to be editing multiple objects

In my Sudoku Android application I have a solve function that solves a Sudoku puzzle (a CellField object). However for some reason when I clone a CellField object and I call the solve method on the cloned object, the solve method solves both of the CellField objects but I only want it to solve the cloned CellField object and not the original object. Any suggestions? Thanks
Here I clone the CellField object (the clone is called temp) and also call the solve method
CellField temp = null;
try {
temp = board.cf.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
int x = randInt(0,8);
int y = randInt(0,8);
while (!temp.getCell(y,x).isEditable && board.cf.getCell(y,x).getValue() == 0) {
x = randInt(0,8);
y = randInt(0,8);
}
SudokuSolver solver = new SudokuSolver();
solver.solve(temp);
Here is my solve method and SudokuSolver class
package com.example.czhou.myapplication2;
import java.util.*;
public class SudokuSolver {
static boolean retry;
public static int randInt(ArrayList<Integer> candidates) {
int min = 0;
int max = candidates.size() - 1;
//inclusive
Random rand = new Random();
int randomNum = rand.nextInt((max - min) + 1) + min;
int result = candidates.get(randomNum);
candidates.remove(randomNum);
return result;
}
public boolean solve(CellField field) {
// write your code here
boolean isValid = true;
Set<Integer> toRemove = new HashSet<>();
int i;
int j;
for (int k = 0; k < 9; k++) {
for (int l = 0; l < 9; l++) {
field.getCell(k, l).restAlt();
if (field.getCell(k, l).alt.indexOf(field.getCell(k, l).getValue()) != -1) {
field.getCell(k, l).alt.remove(field.getCell(k, l).alt.indexOf(field.getCell(k, l).getValue()));
}
}
}
for (i = 0; i < 9; i++) {
for (j = 0; j < 9; j++) {
if (field.getCell(i,j).getValue() == 0 && field.getCell(i,j).alt.size() == 0){
field.getCell(i,j).restAlt();
}
if (field.getCell(i, j).isEditable) {
toRemove.clear();
for (int k = 0; k < 9; k++) {
toRemove.add(field.getCell(k, j).getValue());
}
toRemove.addAll(field.getSectorCandidates(i, j));
for (int k = 0; k < 9; k++) {
toRemove.add(field.getCell(i, k).getValue());
}
toRemove.removeAll(Collections.singleton(0));
field.getCell(i, j).alt.removeAll(toRemove);
if (toRemove.size() == 9 || field.getCell(i, j).alt.size() == 0) {
//When there no candidates are available
//in the current cell, come here
//toRemove.clear();
Cell cell;
boolean stop = false;
backtrack:
for (int k = j; !stop; k--) {
if (k == -1) {
if (i != 0) {
--i;
} else {
break;
}
k = 8;
}
j = k;
// Scan for previous cells have alternative candidates
cell = field.getCell(i, k);
if (cell.alt.size() > 0 && cell.isEditable) {
//bookmark the original cell
//int nextCell = k+1;
// If found a cell set value as first alternative
cell.setValue(cell.alt.get(0));
break backtrack;
} else if (cell.isEditable){
// if no alternatives set cell to 0 and continue backwards
cell.setValue(0);
}
}
} else {
field.getCell(i, j).setValue(randInt(field.getCell(i, j).alt));
}
}
}
}
// for (int m = 0; m < 9; m++) {
// for (int l = 0; l < 9; l++) {
// if (l == 0) {
// System.out.println();
// }
// System.out.print(field.getCell(m, l).getValue());
// }
// }
// System.out.println();
// System.out.println("================");
return isValid;
}
}
Here is my CellField class
package com.example.czhou.myapplication2;
import android.util.Log;
import java.io.Serializable;
import java.util.*;
import java.util.regex.Matcher;
public class CellField implements Cloneable{
protected Cell[][] field = new Cell[9][9];
public CharSequence timeElapsed = "00:00";
public CellField() {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
field[i][j] = new Cell();
}
}
}
public CellField(CellField another) {
List<Cell[]> cellfield = Arrays.asList(another.field);
this.field = (Cell[][]) cellfield.toArray();
}
public CellField clone() throws CloneNotSupportedException {
return (CellField)super.clone();
}
}
The problem is with you Clone method, as #ρяσѕρєя said, you should do a deep copy. Because right now you are returning the same reference. Try something like this:
public CellField clone() throws CloneNotSupportedException {
CellField clone = new CellField();
clone.field = this.field;
clone.timeElapsed = this.timeElapsed;
return clone;
}
It is a matter of shallow copy versus deep copy.
class SomeClass implements Cloneable {
// This is the problematic field. It doesn't get cloned the way you think it is.
public Integer[] field = new Integer[5];
public SomeClass clone() throws CloneNotSupportedException {
return (SomeClass) super.clone();
}
}
public class HelloWorld {
public static void main(String []args){
SomeClass first = new SomeClass();
SomeClass second = null;
try {
second = first.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
System.out.println(first.field);
System.out.println(second.field);
// Their addresses in memory are the same
// Modifying one would modify the other
// first.field == second.field -> true
}
}
In the above example, I cloned one instance of the class into another and, yet, they share the same field. Mutating fields of the first instance of the class will directly affect the field in the second instance of the class since they both own a reference to it.
Instead of using Cloneable, you could define a copy constructor and perform the cloning on your own.
More advanced details can be found on How to properly override clone method?

Java Generics Bound mismatch

Here is a implementation of a generic search algorithm:
The interface:
public interface Comparable<T extends Comparable<T>> {
int compare(T arg);
}
CompareSort.java
public abstract class CompareSort<T extends Comparable<T>> {
protected boolean less(T v, T w) {
return (v.compare(w) < 0);
}
protected void swap(T[] args, int i, int j) {
T swap = args[i];
args[i] = args[j];
args[j] = swap;
}
public abstract void sort(T[] args);
}
One of the algorithm:
public class SelectionSort <T extends Comparable<T>> extends CompareSort<T> {
#Override
public void sort(T[] args) {
int N = args.length;
for (int i = 0; i < N; i++) {
int min = i;
for (int j = i + 1; j < N; j++) {
if (less(args[j], args[min])) {
min = j;
}
}
swap(args, i, min);
}
}
}
And finally a main method to sort Strings.
public class StringSorter {
public static <T extends Comparable<T>> void main(String[] args) throws IOException {
ArrayList<String> list = new ArrayList<String>();
int i = 0;
while (i < 10) {
Scanner s = new Scanner(System.in);
String str = s.nextLine();
list.add(str);
i++;
}
String[] a = list.toArray(new String[list.size()]);
// Create a sort object, use it on a, and print the sorted array.
SelectionSort<String> selection = new SelectionSort<String>();
selection.sort(a);
for (i = 0; i < a.length; i++) {
System.out.println(a[i]);
}
}
}
Here is the problem:
SelectionSort<String> selection = new SelectionSort<String>();
Bound mismatch: The type String is not a valid substitute for the bounded parameter (T extends Comparable(T)) of the type SelectionSort(T)
(box brackets = curved brackets)
Where is the problem? I can not figure it out...
the generic parameter T is extended as well.
Instead of creating your own Comparable, which String does not implement, use Java's java.lang.Comparable, which String does implement.

Algorithm course: Output of int sort and method to sort Strings

My assignment asks me to make a TV show program, where I can input shows, delete, modify and sort them. What I'm stuck on is the sorting part. With the show, it asks for the name, day a new episode premieres, and time. Those are the keys I need to sort it by.
The program prompts the user to input one of those keys, then the program needs to sort (sorting by day will sort alphabetically).
I made a class and used an array. Here is the class:
public class showInfo
{
String name;
String day;
int time;
}
And the method to sort by time in the code:
public static void intSort()
{
int min;
for (int i = 0; i < arr.length; i++)
{
// Assume first element is min
min = i;
for (int j = i+1; j < arr.length; j++)
{
if (arr[j].time < arr[min].time)
{
min = j;
}
}
if (min != i)
{
int temp = arr[i].time;
arr[i].time = arr[min].time;
arr[min].time = temp;
}
}
System.out.println("TV Shows by Time");
for(int i = 0; i < arr.length; i++)
{
System.out.println(arr[i].name + " - " + arr[i].day + " - " + arr[i].time + " hours");
}
}
When I call it and output it in the main, it only shows "TV Shows by Time" and not the list. Why is this?
Also, I need to make ONE method that I will be able to use to sort both the day AND the name (both Strings). How can I do this without using those specific arrays (arr[i].name, arr[i].day) in the method?
Any help would be greatly appreciated! Thanks in advance!
In this part of your code
if (min != i) {
int temp = arr[i].time;
arr[i].time = arr[min].time;
arr[min].time = temp;
}
You're just changing the time when you should move the whole object instead. To fix it, the code must behave like this:
if (min != i) {
//saving the object reference from arr[i] in a temp variable
showInfo temp = arr[i];
//swapping the elements
arr[i] = arr[min];
arr[min] = temp;
}
I̶t̶ ̶w̶o̶u̶l̶d̶ ̶b̶e̶ ̶b̶e̶t̶t̶e̶r̶ ̶t̶o̶ ̶u̶s̶e̶ ̶ Arrays#sort ̶w̶h̶e̶r̶e̶ ̶y̶o̶u̶ ̶p̶r̶o̶v̶i̶d̶e̶ ̶a̶ ̶c̶u̶s̶t̶o̶m̶ ̶̶C̶o̶m̶p̶a̶r̶a̶t̶o̶r̶̶ ̶o̶f̶ ̶t̶h̶e̶ ̶c̶l̶a̶s̶s̶ ̶b̶e̶i̶n̶g̶ ̶s̶o̶r̶t̶e̶d̶ ̶(̶i̶f̶ ̶y̶o̶u̶ ̶a̶r̶e̶ ̶a̶l̶l̶o̶w̶e̶d̶ ̶t̶o̶ ̶u̶s̶e̶ ̶t̶h̶i̶s̶ ̶a̶p̶p̶r̶o̶a̶c̶h̶)̶.̶ ̶S̶h̶o̶r̶t̶ ̶e̶x̶a̶m̶p̶l̶e̶:̶
showInfo[] showInfoArray = ...
//your array declared and filled with data
//sorting the array
Arrays.sort(showInfoArray, new Comparator<showInfo>() {
#Override
public int compare(showInfo showInfo1, showInfo showInfo2) {
//write the comparison logic
//basic implementation
if (showInfo1.getTime() == showInfo2.getTime()) {
return showInfo1.getName().compareTo(showInfo2.getName());
}
return Integer.compare(showInfo1.getTime(), showInfo2.getTime());
}
});
//showInfoArray will be sorted...
Since you have to use a custom made sorting algorithm and support different ways to sort the data, then you just have to change the way you compare your data. This mean, in your current code, change this part
if (arr[j].time < arr[min].time) {
min = j;
}
To something more generic like
if (compare(arr[j], arr[min]) < 0) {
min = j;
}
Where you only need to change the implementation of the compare method by the one you need. Still, it will be too complex to create and maintain a method that can support different ways to compare the data. So the best option seems to be a Comparator<showInfo>, making your code look like this:
if (showInfoComparator.compare(arr[j], arr[min]) < 0) {
min = j;
}
where the showInfoComparator holds the logic to compare the elements. Now your intSort would become into something more generic:
public static void genericSort(Comparator<showInfo> showInfoComparator) {
//your current implementation with few modifications
//...
//using the comparator to find the minimum element
if (showInfoComparator.compare(arr[j], arr[min]) < 0) {
min = j;
}
//...
//swapping the elements directly in the array instead of swapping part of the data
if (min != i) {
int temp = arr[i].time;
arr[i].time = arr[min].time;
arr[min].time = temp;
}
//...
}
Now, you just have to write a set of Comparator<showInfo> implementations that supports your custom criteria. For example, here's one that compares showInfo instances using the time field:
public class ShowInfoTimeComparator implements Comparator<showInfo> {
#Override
public int compare(showInfo showInfo1, showInfo showInfo2) {
//write the comparison logic
return Integer.compare(showInfo1.getTime(), showInfo2.getTime());
}
}
Another comparator that uses the name field:
public class ShowInfoNameComparator implements Comparator<showInfo> {
#Override
public int compare(showInfo showInfo1, showInfo showInfo2) {
//write the comparison logic
return showInfo1.getName().compareTo(showInfo2.getName());
}
}
Now in your code you can call it like this1:
if (*compare by time*) {
genericSort(showInfoArray, new ShowInfoTimeComparator());
}
if (*compare by name*) {
genericSort(showInfoArray, new ShowInfoNameComparator());
}
if (*another custom rule*) {
genericSort(showInfoArray, new ShowInfoAnotherCustomRuleComparator());
}
where now you can implement a custom rule like compare showInfo objects using two or more fields. Taking as example your name and day fields (as stated in the question):
public class ShowInfoNameAndDayComparator implements Comparator<showInfo> {
#Override
public int compare(showInfo showInfo1, showInfo showInfo2) {
//write the comparison logic
int nameComparisonResult = showInfo1.getName().compareTo(showInfo2.getName());
if (nameComparisonResult == 0) {
return showInfo1.getDay().compareTo(showInfo2.getDay());
}
return nameComparisonResult;
}
}
1: There are other ways to solve this instead using lot of if statements, but looks like that's outside the question scope. If not, edit the question and add it to show another ways to solve this.
Other tips for your current code:
Declare the names of the classes using CamelCase, where the first letter of the class name is Upper Case, so your showInfo class must be renamed to ShowInfo.
To access to the fields of a class, use proper getters and setters instead of marking the fields as public or leaving the with default scope. This mean, your ShowInfo class should become into:
public class ShowInfo {
private String name;
private String day;
private int time;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
//similar for other fields in the class
}
Use selection sort algorithm which is easy to implement,
for (int i = 0; i < arr.length; i++)
{
for (int j = i + 1; j < arr.length; j++)
{
if (arr[i].time > arr[j].time) // Here ur code that which should be compare
{
ShowInfo temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
no need to check min element. go through this wiki http://en.wikipedia.org/wiki/Selection_sort
Why not you use a Collection for this sort of a thingy to work. Moreover, in your added example, you are simply changing one attribute of a given object, while sorting, though you not changing the position of the object as a whole, inside the given list.
Create a List which will contain the references of all the Shows, now compare each attribute of one Show with another, in the List. Once the algorithm feels like, that swapping needs to be done, simply pick the reference from the List, save it in a temp variable, replace it with a new reference at this location, and set duplicate to the one stored in the temp variable. You are done, List is sorted :-)
Here is one small example for the same, for help :
import java.io.*;
import java.util.*;
public class Sorter {
private BufferedReader input;
private List<ShowInfo> showList;
public Sorter() {
showList = new ArrayList<ShowInfo>();
input = new BufferedReader(
new InputStreamReader((System.in)));
}
private void createList() throws IOException {
for (int i = 0; i < 5; i++) {
System.out.format("Enter Show Name :");
String name = input.readLine();
System.out.format("Enter Time of the Show : ");
int time = Integer.parseInt(input.readLine());
ShowInfo show = new ShowInfo(name, time);
showList.add(show);
}
}
private void performTask() {
try {
createList();
} catch (Exception e) {
e.printStackTrace();
}
sortByTime(showList);
}
private void sortByTime(List<ShowInfo> showList) {
int min;
for (int i = 0; i < showList.size(); i++) {
// Assume first element is min
min = i;
for (int j = i+1; j < showList.size(); j++) {
if (showList.get(j).getTime() <
showList.get(min).getTime()) {
min = j;
}
}
if (min != i) {
ShowInfo temp = showList.get(i);
showList.set(i, showList.get(min));
showList.set(min, temp);
}
}
System.out.println("TV Shows by Time");
for(int i = 0; i < showList.size(); i++) {
System.out.println(showList.get(i).getName() +
" - " + showList.get(i).getTime());
}
}
public static void main(String[] args) {
new Sorter().performTask();
}
}
class ShowInfo {
private String name;
int time;
public ShowInfo(String n, int t) {
name = n;
time = t;
}
public String getName() {
return name;
}
public int getTime() {
return time;
}
}
EDIT 2 :
For sorting By Name you can use this function :
private void sortByName(List<ShowInfo> showList) {
int min;
for (int i = 0; i < showList.size(); i++) {
// Assume first element is min
min = i;
for (int j = i+1; j < showList.size(); j++) {
int value = (showList.get(j).getName()).compareToIgnoreCase(
showList.get(min).getName());
if (value < 0)
min = j;
}
if (min != i) {
ShowInfo temp = showList.get(i);
showList.set(i, showList.get(min));
showList.set(min, temp);
}
}
System.out.println("TV Shows by Time");
for(int i = 0; i < showList.size(); i++) {
System.out.println(showList.get(i).getName() +
" - " + showList.get(i).getTime());
}
}
EDIT 3 :
Added Comparable<?> Interface, to the existing class to perform sorting based on specified input. Though one can improve on the logic, by using Enumeration, though leaving it for the OP to try his/her hands on :-)
import java.io.*;
import java.util.*;
public class Sorter {
private BufferedReader input;
private List<ShowInfo> showList;
private int command;
public Sorter() {
showList = new ArrayList<ShowInfo>();
input = new BufferedReader(
new InputStreamReader((System.in)));
command = -1;
}
private void createList() throws IOException {
for (int i = 0; i < 5; i++) {
System.out.format("Enter Show Name :");
String name = input.readLine();
System.out.format("Enter Time of the Show : ");
int time = Integer.parseInt(input.readLine());
ShowInfo show = new ShowInfo(name, time);
showList.add(show);
}
}
private void performTask() {
try {
createList();
} catch (Exception e) {
e.printStackTrace();
}
System.out.format("How would you like to sort : %n");
System.out.format("Press 0 : By Name%n");
System.out.format("Press 1 : By Time%n");
try {
command = Integer.parseInt(input.readLine());
} catch (Exception e) {
e.printStackTrace();
}
sortList(showList);
}
private void sortList(List<ShowInfo> showList) {
int min;
for (int i = 0; i < showList.size(); i++) {
// Assume first element is min
min = i;
for (int j = i+1; j < showList.size(); j++) {
showList.get(j).setValues(command);
int value = showList.get(j).compareTo(showList.get(min));
if (value < 0) {
min = j;
}
}
if (min != i) {
Collections.swap(showList, i, min);
}
}
System.out.println("TV Shows by Time");
for(int i = 0; i < showList.size(); i++) {
System.out.println(showList.get(i).getName() +
" - " + showList.get(i).getTime());
}
}
public static void main(String[] args) {
new Sorter().performTask();
}
}
class ShowInfo implements Comparable<ShowInfo> {
private String name;
private int time;
private int command;
public ShowInfo(String n, int t) {
name = n;
time = t;
}
public String getName() {
return name;
}
public int getTime() {
return time;
}
public void setValues(int cmd) {
command = cmd;
}
public int compareTo(ShowInfo show) {
int lastCmp = 1;
if (command == 0) {
lastCmp = name.compareTo(show.name);
} else if (command == 1) {
if (time < show.time) {
lastCmp = -1;
} else if (time == show.time) {
lastCmp = 0;
} else if (time > show.time) {
lastCmp = 1;
}
}
return lastCmp;
}
}

Categories