Создание моего собственного типа данных

#java

#java

Вопрос:

Я новичок в программировании и Java. Я пытаюсь написать свой собственный тип данных / класс коллекции, но я не совсем уверен, как это сделать.

Мне нужен класс, содержащий строку, и массив-список строк.

Обычно я бы предпочел создать тип данных, подобный этому:

 public class Collection {

    private int id;
    private String word;
    private int howMany;
    private char firstChar;

    public Collection (int i, String w, int h, char f){
        id = i;
        word = w;
        howMany = h;
        firstChar = f;
    }
//Getters and Setters
}
  

Не уверен, как я могу сделать это с полем ArrayList.

Моя цель, стоящая за этим, — создать класс уникальных слов в поле string, считываемых из файлов .txt, а в поле arraylist — все имена файлов .txt, содержащие это слово.

Редактировать: основываясь на ответе Тома Андерсона и на том, что я изначально думал сделать:

 public class Collection {

    private int id;
    private String word;
    private int howMany;
    private char firstChar;
    private List<String> filenames;

    public Collection (int i, String w, int h, char f, List<String> filenames){
        id = i;
        word = w;
        howMany = h;
        firstChar = f;
        this.filenames = filenames;
    }

}
  

Я все еще не уверен, как это использовать, поскольку я не могу просто добавить строку в параметр ArrayList при создании нового экземпляра класса my Collection. Например, это:

 ArrayList<Collection> collection = new ArrayList<Collection>();
Collection newTest= new Collection("test","test");
collection.add(newTest);
  

Комментарии:

1. если вы пытаетесь реализовать поиск / индексирование, вы могли бы использовать lucene. Вы могли бы создать свою собственную коллекцию, либо расширив коллекцию, либо инкапсулировав ее.

2. Что это за Collection конструктор, который вы вызываете в своем последнем фрагменте? Вы раньше не показывали конструктор, который принимает две строки.

Ответ №1:

Прежде чем я продолжу, Collection это неподходящее название для класса, потому что в java.util пакете уже есть чрезвычайно популярный класс с таким именем. Я буду называть ваш класс вхождениями.

Чтобы принять ваш вопрос за чистую монету, это было бы:

 public class Occurrences {

    private int id;
    private String word;
    private int howMany;
    private char firstChar;
    private List<String> filenames;

    public Occurrences (int i, String w, int h, char f, List<String> filenames){
        id = i;
        word = w;
        howMany = h;
        firstChar = f;
        this.filenames = filenames;
    }

}
  

Вы об этом думали? Какие у вас проблемы с этим?

Есть несколько вещей, о которых стоит упомянуть.

Во-первых, вы запросили ArrayList , но список имен файлов имеет пару отличительных особенностей: он может содержать каждое имя файла только один раз, и порядок имен файлов не имеет значения (я предполагаю). Это означает, что на самом деле это Set , а не a List ; класс реализации для использования здесь был бы HashSet .

Во-вторых, вам все еще нужно создать эту коллекцию имен файлов, и, возможно, именно здесь вы зашли в тупик. Вы читаете эту информацию из файла? Если это так, допустим, у вас есть список имен файлов в строке, разделенный запятыми. Нравится:

 String filenamesStr = "one.txt,two.txt,three.txt";
  

Самый простой способ превратить их в набор — это разделить их на массив, обернуть массив в список и использовать список для построения набора (да, действительно!):

 Set<String> filenames = new HashSet<String>(Arrays.asList(filenamesStr.split(",")));
  

В качестве альтернативы, вы можете создавать имена файлов по мере обработки файлов. В этом случае, возможно, то, что вам следует сделать, это позволить классу Occurrences накапливать их:

 public class Occurrences {

    private int id;
    private String word;
    private int howMany;
    private char firstChar;
    private Set<String> filenames;

    public Occurrences (int i, String w){
        id = i;
        word = w;
        firstChar = w.charAt(0); // bonus feature!
        howMany = 0;
        filenames = new HashSet<String>();
    }

    public void addOccurrence(String filename) {
          howMany;
        filenames.add(filename);
    }

}
  

Затем, когда вы индексируете свои файлы, просто вызывайте addOccurrence каждый раз, когда видите слово.

В-третьих, как указывали другие участники ответа, Map было бы хорошим способом организовать всю вашу вселенную слов. Вы можете использовать word в качестве ключа и либо Occurences , либо необработанную коллекцию имен файлов в качестве значения, в зависимости от того, что вам действительно нужно.

Комментарии:

1. Это именно то, о чем я думал, но причина, по которой я не думал, что это сработает, заключается в том, что при создании нового экземпляра класса, как бы я просто добавил строку в arraylist . Простое выполнение этого не работает. Коллекция newTest= новая коллекция («test»,»тест»); collection.add(newTest);

2. Для этого есть старый трюк, когда вы хотите сразу добавить некоторые значения в коллекцию… Коллекция<Строка> newTest = новый список массивов<Строка>() {{ добавить(«тест»); добавить(«тест») }};

3. @jkschneider: Ах, старый инициализатор с двойными скобками. Это кажется довольно бесполезным его использованием, учитывая существование Arrays.asList ; однако, это, безусловно, очень полезно для инициализации maps.

4. @Tom: Помните, что Arrays.asList возвращает неизменяемый список. Позже он больше ничего не смог добавить…

5. @jkschneider: Совершенно верно. Обычно вам нужно передать этот список прямо в конструктор какой-нибудь другой коллекции.

Ответ №2:

На самом деле вам не нужен ваш собственный тип данных. Для этого и предназначен класс Map:

 public void someMethod() {
    Map<String, Collection<String>> filesByUniqueWord = new HashMap<String, Collection<String>>();

    // inserting new entries
    String uniqueWord = "hi";      
    List<String> filesContainingWord;  // assume you have this        
    filesByUniqueWord.put(uniqueWord, filesContainingWord);

    // deleting entries
    filesByUniqueWord.remove(uniqueWord);

    // getting all the files that contain some word
    List<String> retrieved = filesByUniqueWord.get("hi"); // retrieved == filesContainingWord
}
  

Ответ №3:

Прежде всего, не вызывайте class Collection, это будет очень запутанно, поскольку Collection существует как часть библиотеки java.util.

Во-вторых, я предполагаю, что вы действительно хотите написать коллекцию, потому что вы учитесь, как это сделать, в противном случае, пожалуйста, используйте HashMap или какой-либо другой вид карты, как описано в некоторых других ответах.

Итак, предполагая, что вы действительно хотите написать коллекцию самостоятельно, я предлагаю реализовать один из стандартных интерфейсов Java. Либо java.util.Коллекция или итерируемый. Этот второй вариант был бы самым простым.

Итак, что-то вроде

класс MyCollection расширяет возможности итерации {

 частная строка yourString;
 частная строка theArray;
 общедоступная коллекция MyCollection(строка yourString, Строка[] theArray) {
 this.yourString = yourString;
 this.theArray = theArray
 }

 общедоступное логическое значение hasNext() {
 // Посмотрим, есть ли следующий элемент для возврата
 ...
 }

 общедоступная строка next() {
 // верните следующий
 }
}

Ответ №4:

Что вам нужно, так это список строк. Теперь, увидев ваш код, я предполагаю, что мы будем использовать методы получения и установки. Поэтому, когда вы используете установщики, я думаю, что не лучшая практика присваивать значения вашим переменным внутри конструктора. Вместо этого вы можете просто создать свои объекты внутри своего конструктора

 public class Collection { 

private int id; 
private String word; 
private int howMany; 
private char firstChar;
private ArrayList<String> txtFiles; 

public Collection (int i, String w, int h, char f){ 
    word=new String();
    txtFiles=new ArrayList<String>();
  } 
} 
  

Теперь для вашего ArrayList вы можете использовать такие методы, как

 Add(String file)
Remove(String file)
  

Для добавления и удаления имен файлов

И для установки других переменных используйте геттеры и установщики, такие как

 setId(int id)
getId()
  

Другая логика кодирования зависит от вас, но я думаю, что именно так вы должны проектировать свой класс

Ответ №5:

То, что вам нужно сделать, может быть сделано с помощью HashMap. Пример которого можно получить здесь.

Вы можете сделать что-то вроде этого:

 Map<String, List<String>> myMap = new HashMap<String, List<String>>();
  

Затем загрузите файлы и сделайте то, что вам нужно.