I have the following code for sorting. Can this be improved?
import java.util.*;
class Church {
private String name;
private String pastor;
public Church(String name, String pastor) {
this.name = name;
this.pastor = pastor;
}
public String getPastor() {
return pastor;
}
public String getName() {
return name;
}
public void setPastor(String pastor) {
this.pastor = pastor;
}
public String toString() {
return getName() + " is Pastored by "+getPastor();
}
public int compareByPastor(Church c) {
int x = pastor.compareTo(c.getPastor());
return x;
}
public int compareByName(Church c) {
int x = name.compareTo(c.getName());
return x;
}
}
class Churches {
private final List<Church> churches;
public Churches() {
churches = new ArrayList<Church>();
}
public void addWithoutSorting(Church c) {
churches.add(c);
}
//You could always add using this method
public void addWithSorting(Church c) {
}
public void display() {
for(int j = 0; j < churches.size(); j++) {
System.out.print(churches.get(j).toString());
System.out.println("");
}
}
public List<Church> getChurches() {
return churches;
}
public void sortBy(String s) {
for (int i = 1; i < churches.size(); i++) {
int j;
Church val = churches.get(i);
for (j = i-1; j > -1; j--) {
Church temp = churches.get(j);
if(s.equals("Pastor")) {
if (temp.compareByPastor(val) <= 0) {
break;
}
}
else if(s.equals("Name")) {
if (temp.compareByName(val) <= 0) {
break;
}
}
churches.set(j+1, temp);
}
churches.set(j+1, val);
}
}
public static void main(String[] args) {
Churches baptists = new Churches();
baptists.addWithoutSorting(new Church("Pac", "Pastor G"));
baptists.addWithoutSorting(new Church("New Life", "Tudor"));
baptists.addWithoutSorting(new Church("My Church", "r035198x"));
baptists.addWithoutSorting(new Church("AFM", "Cathy"));
System.out.println("**********************Before Sorting***********************");
baptists.display();
baptists.sortBy("Pastor");
System.out.println("**********************After sorting by Pastor**************");
baptists.display();
baptists.sortBy("Name");
System.out.println("**********************After sorting by Name****************");
baptists.display();
}
}
Take a look at Collections.sort(list, comparator)
http://download.oracle.com/javase/6/docs/api/java/util/Collections.html
class Churches
{
public void sortBy(String attribute)
{
Comparator<Church> c = null;
if ("Name".equals(attribute)) c = new ChurchNameComparator();
else if ("Pastor".equals(attribute)) c = new ChurchNameComparator();
else System.out.println("unexpected sort attribute : '" + attribute + "'");
if (c != null) Collections.sort(churches, c);
}
private static final class ChurchNameComparator implements Comparator<Church>
{
public int compare(Church c1, Church c2)
{
return c1.getName().compareTo(c2.getName());
}
}
private static final class ChurchPastorComparator implements Comparator<Church>
{
public int compare(Church c1, Church c2)
{
return c1.getPastor().compareTo(c2.getPastor());
}
}
}
The real answer here is pretty much in line with iluxa's: you want to implement a Comparator interface on your Church objects (sample code here, though you'll want to decide what constitutes greater than/less than for a church...), and then you can use Collections.sort() to sort them. That will get the job done, at the end of the day.
Of course, you just asked for advice about sorting on Stack Overflow, so I feel compelled to ask you if you need an in-place sort, what kind of Big-O performance you're looking for, and then ask you to choose between Quicksort, IntroSort, HeapSort, MergeSort, and StoogeSort for what will work best for you.
For kicks, I once coded up a few sorts in Java:
This one forces Quicksort into quadratic time, which was harder to do than I'd originally assumed,
This one shows how to implement MergeSort,
and this one demonstrates a HeapSort
I did these for my own enjoyment and education. As a general rule, you want to stick with the standard library for these sorts of things.
Related
I'm learning object-oriented programming and started learning about inheritance. The assignment my teacher gave me was to make a counter object with 6 "buttons": Increment, Decrement, Reset, AddMemory, ResetMemory, and Quit. It is fairly straight-forward what each button does.
The requirements are that I have to use the JOptionPane command, I have to make a Counter class with a counter attribute, increment, decrement, reset, and quit methods, I have to make a MemoryCounter class with a memory attribute, restMemory, and addMemory method. I also have to make a MemoryCounterConsoleMenu class which makes the input box from the JOptionPane command and executes the appropriate method. The final thing I have to do is make a MemoryCounterTest class that brings the MemoryCounterConsoleMenu and MemoryCounter classes together
So I did all that and here it is:
The first one is the Counter class
public class Counter
{
private int counter = 0;
public void increment()
{
setCounter(getCounter() + 1);
}
public void decrement()
{
setCounter(getCounter() - 1);
}
public void reset()
{
setCounter(0);
}
public void setCounter(int counter) {
this.counter = counter;
}
public int getCounter() {
return counter;
}
}
This is the MemoryCounter class
public class MemoryCounter extends Counter
{
private int memory = 0;
public void resetMem()
{
setMemory(0);
}
public void addMem()
{
setMemory(getCounter());
}
public void setMemory(int memory)
{
this.memory = memory;
}
public int getMemory()
{
return memory;
}
}
Next is the MemoryConsoleMenu
public class MemoryCounterConsoleMenu
{
static MemoryCounter memCounter = new MemoryCounter();
static Counter counter = new Counter();
public static int console()
{
System.out.println(memCounter.getMemory());
Object[] options = {"Reset Mem", "Add Mem", "Increment", "Decrement", "Reset", "Quit" };
int objectIndex = JOptionPane.showOptionDialog(null, "Counter = " + counter.getCounter() + "Memory = "
+ memCounter.getMemory(), "MemoryCounter",JOptionPane.PLAIN_MESSAGE,
JOptionPane.PLAIN_MESSAGE, null, options, options[5]);
return objectIndex;
}
public static int change(int objectIndex)
{
if(objectIndex == 0)
{
memCounter.resetMem();
return 1;
}
else if(objectIndex == 1)
{
memCounter.addMem();
return 2;
}
else if(objectIndex == 2)
{
counter.increment();
return 3;
}
else if(objectIndex == 3)
{
counter.decrement();
return 4;
}
else if(objectIndex == 4)
{
counter.reset();
return 5;
}
else
{
return 6;
}
}
}
Finally, there is the MemoryCounterTest
public class MemoryCounterTest
{
public static void main(String[] args)
{
MemoryCounterConsoleMenu memoryConsole = new MemoryCounterConsoleMenu();
for(int i = 0; i != 6;)
{
i = memoryConsole.change(memoryConsole.console());
}
}
}
Everything works properly except for the memory value. It stays at a constant zero. I've done some troubleshooting myself and found that the only problem in the code is in the "addMem()" method is the MemoryCounter class particularly the implementation of the "getCounter()" method. It will only return 0 for some reason.
After figuring this out I have made no ground on why the problem is occuring or how to fix it
It stays at 0 because they are two separate counters.
MemoryCounter class extends the Counter class, so you don't need a separate
static Counter counter = new Counter();
Just do everything via memCounter.
I'm doing an exercise, in which I have to create the method add, however due to p and v being defined as objects, I'm having a hard time figuring out how I can define this method in the syntax I've been given in the exercise (I'm only allowed to change the methods).
I would like to add the two inputs 5 and 17 so that it returns 22. I've done a lot of research into other questions where I've seen them write it as Positiv(p + v) but this doesn't quite work.
public class Positiv {
public static void main(String[] args) {
try {
Positiv p = new Positiv(5);
Positiv v = new Positiv(17);
p.add(v);
System.out.println(p.get());
} catch (Exception e) {
e.printStackTrace();
}
}
private int n;
public Positiv(int n) {
if (n < 0) { throw new IllegalArgumentException("exception");
}
this.n = n;
}
public static Positiv add(Positiv v)
{
return new Positiv(n + v);
}
public int get() {
return n;
}
}
In your add method:
public static Positiv add(Positiv v)
{
return new Positiv(n + v);
}
You return a whole new Positiv object. However (correct me if I'm wrong) it looks as if you just want to add the two n fields. You can do this by adding this.get to v.get:
public void add(Positiv v)
{
this.n += v.get();
}
Which will return 22
Tutorial for this
public class HelloWorld{
public static void main(String []args){
Numbers a = new Numbers(5);
Numbers b = new Numbers(10);
int num1 = a.getN();
int num2 = b.getN();
System.out.println(addTwoNumbers(num1, num2));
}
public static int addTwoNumbers(int a, int b) {
return a + b;
}
}
class Numbers {
private int n;
public Numbers(int n) {
this.n = n;
}
public int getN() {
return n;
}
}
I am trying to write a generic heap class.
import java.util.ArrayList;
public class heap<T extends Comparable<T>>
{
private ArrayList<T> h;
private int size;
public heap()
{
h = new ArrayList<T>();
h.add(null);
size = 0;
}
public T getMin()
{
return h.get(1);
}
public T popMin()
{
T tmp = getMin();
h.set(1, h.get(size));
size--;
sift(1);
return tmp;
}
public void insert(T key)
{
h.add(key);
percolate(++size);
}
public int getSize()
{
return this.size;
}
private int getLeftSon(int i)
{
return (i<<1<=size)? i<<1 : 0;
}
private int getRightSon(int i)
{
return ((i<<1)+1<=size)? (i<<1)+1 : 0;
}
private int getFather(int i)
{
return ((i>>1)!=0)? i>>1 : 0;
}
private void swap(int i, int j)
{
T tmp = h.get(i);
h.set(i, h.get(j));
h.set(j, tmp);
}
private void sift(int i)
{
int son;
do {
son = 0;
if (getLeftSon(i) != 0)
{
son = getLeftSon(i);
if (getRightSon(i) != 0 && h.get(getRightSon(i)).compareTo(h.get(getLeftSon(i))) > 0)
son = getRightSon(i);
if (h.get(son).compareTo(h.get(i)) <= 0)
son = 0;
}
if (son!=0) {
swap(i, son);
i = son;
}
} while (son!=0);
}
private void percolate(int i)
{
T key = h.get(i);
while ((i > 1) && (key.compareTo(h.get(getFather(i))) > 0))
{
h.set(i, h.get(getFather(i)));
i = getFather(i);
}
h.set(i, key);
}
}
All good. It works like a charm. Excepting one thing: if I work with Integers I don't have 'access' to the method compareTo from Integer. meaning that I can not override it's behaviour. I will always have a Max heap this way. Can Integer compareTo by override (I don't think it can)?
So what can I do apart from creating another class MyInteger extends Integer{...} and override it there.
You could make your heap accept a Comparator in constructor and then provide a Comparator that reverses the order.
That's what the Comparator is for actually - defining an ordering that's not a natural one for the given class, being able to define multiple orderings of the same class, or indeed defining an ordering for a class you cannot modify.
The approach of accepting a comparator at construction time can be seen in TreeSet for example.
Example code stub:
public class Heap<T> { /* no need for items to extend Comparable anymore */
private final Comparator<T> cmp;
public Heap(Comparator<T> cmp) {
this.cmp = cmp;
...
}
...
}
... and then use cmp.compare(item1, item2) wherever you now use item2.compareTo(item2).
I have this Test class and I have to write the others classes code in order to pass the asserts.
That's the Test class:
import java.util.*;
public class Test
{
public static void main(String[] args)
{
Book javabook = new Book("Learn Java",150);
Book cbook = new Book("C",120);
Book[] books = new Book[] {javabook, cbook};
Library lib = new Library(books);
assert(lib.pages() == 270);
List l = lib;
assert(l.size() == 2);
Collections.sort(l);
assert(l.get(0) == cbook);
assert(l.get(1) == javabook);
}
}
I started making the Book class, here is my implementation:
public class Book implements Comparable
{
private String name;
private int pages;
public Book(String name, int pages)
{
this.name = name;
this.pages = pages;
}
public int getPages()
{
return this.pages;
}
public int compareTo(Object obj)
{
if(this == obj) return 0;
else
{
Book x = (Book) obj;
return this.pages - x.pages;
}
}
}
Then I wrote the Library class:
import java.util.*;
public class Library extends ArrayList
{
ArrayList a;
public Library(Book[] b)
{
a = new ArrayList(b.length);
for(int i=0; i<b.length; i++)
{
a.add(b[i]);
}
}
public int pages()
{
int p = 0;
for(int i=0; i<a.size(); i++)
{
p += ( (Book) a.get(i) ).getPages();
}
return p;
}
public int size()
{
return a.size();
}
public Object get(int i)
{
return a.get(i);
}
}
I think the problem is on the Library class, seems like the Collections.sort doesn't work and I can't pass the asserts after the call of the method sort in the Test class! I can't figure out what's the problem on my code, can someone help me please?
Remember: I have to make my code in order to pass the asserts.
I'm not sure about my Library implementation in order to make this line on the Test work:
List l = lib;
Not sure about the ArrayList extension.
P.S. I know it's better to use generic types but I mustn't use them for this exercise. Without using them I get some warnings, just ignore them.
Your implementation of the Library class is indeed wrong - it shouldn't have a list of Books, it should be a list of Books - that's why it extends an ArrayList:
public class Library extends ArrayList<Book> {
// Note: no additional data members.
// The Library is already a List<Book>:
public Library(Book[] b) {
super(Arrays.asList(b));
}
public int pages() {
int p = 0;
for(int i = 0; i < size(); i++) {
p += get(i).getPages();
}
return p;
}
}
I tried looking up tutorials and videos and I understand what implementing does, although I'm a bit confused as to how one would implement a class from the Java Library. In my homework, I'm suppose to utilize the class, DataSet and make it so it accepts Comparable objects. The program is suppose to record the Min and Max values depending on the objects, in this case, I'm suppose to use strings. I wasn't sure if I needed any classes to implement the Comparable interface, so I made two classes just in case I was suppose to do so. My real question is how do I actually incorperate a String variable in the tester class to actually read and compare the object to another? thanks in advance.
public class Word implements Comparable
{
private String str;
public Word()
{
str = null;
}
public Word(String s)
{
str = s;
}
public int compareTo(Object other)
{
String n = (String) other;
return str.compareTo(n);
}
}
I wasn't sure which of the two classes would be suitable for implementing Although i think the String class below would not work at all b/c It's already a standard class so I wasn't too sure about using it
public class String implements Comparable
{
public String s;
public String()
{
s = null;
}
public String(String str)
{
s = str;
}
public int compareTo(Object other)
{
String n = (String) other;
return s.compareTo(n);
}
}
public interface Comparable
{
public int compareTo(Object other);
}
public class DataSet
{
private Object maximum;
private Object least;
private Comparable compare;
private int count;
public DataSet(Comparable s)
{
compare = s;
}
public void add(Object x)
{
if(count == 0)
least = x;
if(count == 0 || compare.compareTo(x) >=0)
maximum = x;
else if(compare.compareTo(x) <0)
least = x;
count++;
}
public Object getMaximum()
{
return maximum;
}
public Object getLeast()
{
return least;
}
}
public class DataSetTester
{
public static void main(String[] args)
{
Comparable n = new Word("sand");
DataSet data = new DataSet(n);
data.add(new Word(man));
System.out.println("Maximum Word: " + data.getMaximum());
System.out.println("Least Word: " + data.getLeast());
}
}
An interface is a contract that showes that your class contain all methodes that are implemented in the interface. In this case the CompareTo(object other). The String class already implements the comparable interface so you don't need youre own class. I think your data set class should look something like this :
public class DataSet<T implements Comparable>
{
private T maximum;
private T least;
private T count;
public void add(T x)
{
if(count == 0){
least = x;
maximum = x;
}
else if(least.compareTo(x) > 0)
least = x;
else if(maximum.compareTo(x) < 0)
maximum = x;
count++;
}
public T getMaximum()
{
return maximum;
}
public T getLeast()
{
return least;
}
}
T is a generic type and in your case it should be String, Here is how you create a new Data set:
DataSet<String> ds = new DataSet<String>;