Java associative-array


214

ฉันจะสร้างและดึงข้อมูลอาเรย์แบบเชื่อมโยงใน Java อย่างที่ฉันสามารถทำได้ใน PHP ได้อย่างไร

ตัวอย่างเช่น:

$arr[0]['name'] = 'demo';
$arr[0]['fname'] = 'fdemo';
$arr[1]['name'] = 'test';
$arr[1]['fname'] = 'fname';

คำตอบ:


356

Java ไม่รองรับอาเรย์แบบเชื่อมโยงอย่างไรก็ตามเรื่องนี้สามารถทำได้โดยMapง่ายด้วย เช่น,

Map<String, String> map = new HashMap<String, String>();
map.put("name", "demo");
map.put("fname", "fdemo");
// etc

map.get("name"); // returns "demo"

ตัวอย่างของคุณมีความแม่นยำมากขึ้น (เนื่องจากคุณสามารถแทนที่สตริงด้วยวัตถุใด ๆ ที่ตรงกับความต้องการของคุณ) ก็คือการประกาศ:

List<Map<String, String>> data = new ArrayList<>();
data.add(0, map);
data.get(0).get("name"); 

ดูเอกสารประกอบอย่างเป็นทางการสำหรับข้อมูลเพิ่มเติม


2
นี้จะโยนถ้าแผนที่ด้านนอกไม่ได้มีแผนที่สำหรับรายการNullPointerException 0PHP ไม่อนุญาตด้วย $ arr [0] ['name'] (ฉันไม่รู้ภาษานี้เลย)
Tomasz Nurkiewicz

9
PHP จะไม่เช่นนั้นถ้าคุณพยายามที่จะเข้าถึงคีย์ที่ไม่มีอยู่ไม่มี :)
Svish

2
@edem การดำเนินการบางอย่างจำเป็น อย่างไรก็ตามวันนี้ฉันต้องการได้ArrayListเกือบทุกกรณีเนื่องจากความแตกต่างด้านประสิทธิภาพ (ไม่คาดคิด?) แต่นั่นเป็นอีกการสนทนา
Johan Sjöberg

3
อย่าลืมเริ่มต้นขนาดแฮชที่แน่นอนและตั้งค่าตัวโหลดเป็น 1: HashMap <String, String> (ความจุ 1) มิฉะนั้นคุณอาจใช้โอเวอร์เฮดขนาดใหญ่และวัตถุของคุณต้องการ RAM มาก +1 สำหรับ ArrayList แต่ทำไมไม่มีการแก้ไขคำตอบ?
Marcus

1
@ Marcus " อย่าลืมเริ่มต้นขนาดแฮชที่แน่นอนและตั้งค่าตัวโหลดเป็น 1 " - คุณจะได้รับคำแนะนำจากที่ไหน? คุณแทบไม่ควรระบุตัวประกอบโหลดของ a HashMapและแน่นอนว่าไม่ได้โดยไม่ต้องทำการเปรียบเทียบพฤติกรรมโดยเจตนาและค้นหาตัวประกอบการโหลดที่ดีกว่าสำหรับกรณีการใช้งานของคุณ เหตุผลเดียวที่ระบุขนาดเริ่มต้นคือถ้าคุณรู้ล่วงหน้าว่าแผนที่จะมีขนาดใหญ่มาก HashMapไม่เสียหน่วยความจำ (มาก) ถ้าว่างเปล่า แต่ถ้าคุณตั้งใจจะสร้างแผนที่ขนาดใหญ่คุณสามารถบันทึกการปรับขนาดอาเรย์หลายรายการโดยการระบุขนาดของมันไว้ด้านหน้า
dimo414

47

Java ไม่มีอาร์เรย์ที่เชื่อมโยงเหมือนที่ PHP ทำ

มีวิธีแก้ปัญหาต่าง ๆ สำหรับสิ่งที่คุณทำเช่นใช้แผนที่ แต่ขึ้นอยู่กับว่าคุณต้องการค้นหาข้อมูลอย่างไร ArrayListคุณสามารถเขียนคลาสที่เก็บข้อมูลและจัดเก็บทุกกรณีของพวกเขาในการอื่น

public class Foo{
    public String name, fname;

    public Foo(String name, String fname){
        this.name = name;
        this.fname = fname;
    }
}

แล้ว ...

List<Foo> foos = new ArrayList<Foo>();
foos.add(new Foo("demo","fdemo"));
foos.add(new Foo("test","fname"));

ดังนั้นคุณสามารถเข้าถึงได้เช่น ...

foos.get(0).name;
=> "demo"

20

คุณสามารถทำสิ่งนี้ผ่านแผนที่ สิ่งที่ต้องการ

Map<String, String>[] arr = new HashMap<String, String>[2]();
arr[0].put("name", "demo");

แต่เมื่อคุณเริ่มใช้ Java ฉันมั่นใจว่าคุณจะพบว่าหากคุณสร้างคลาส / โมเดลที่แสดงถึงข้อมูลของคุณจะเป็นตัวเลือกที่ดีที่สุดของคุณ ฉันจะทำ

class Person{
String name;
String fname;
}
List<Person> people = new ArrayList<Person>();
Person p = new Person();
p.name = "demo";
p.fname = "fdemo";
people.add(p);

ฉันคิดว่าฉันชอบวิธีนี้ดีกว่าขอบคุณ มาจาก php ที่ทุกอย่างเรียบง่ายใช้งานง่าย แต่ใช้งานได้ดี ขอบคุณ
frostymarvelous

เหตุใดจึงใช้รายการแทน ArrayList จาวามือใหม่ที่นี่
Sobiaholic

'List' เป็นคลาสนามธรรมและ 'ArrayList' เป็นหนึ่งในการนำไปใช้ของคลาสนั้นมีรายการประเภทอื่นที่ได้มาจากคลาสนามธรรมเดียวกัน ดังนั้นด้วยเหตุนี้ ArrayList จึงเป็น List คุณไม่สามารถสร้างอินสแตนซ์ของคลาสนามธรรมเพียงแค่ใช้มันเป็นประเภทที่นี่คุณต้องใช้การใช้งานสำหรับอินสแตนซ์ของคุณ ดังนั้น List จึงเป็นประเภทและ ArrayList เป็นตัวอย่างที่นี่
veta

12

ไม่มีสิ่งเช่นอาเรย์เชื่อมโยงใน Java สัมพัทธ์ที่ใกล้เคียงที่สุดของมันคือ a Mapซึ่งถูกพิมพ์อย่างมากอย่างไรก็ตามมีไวยากรณ์ / API ที่หรูหราน้อยกว่า

นี่คือตัวอย่างที่ใกล้เคียงที่สุดที่คุณจะได้รับ:

Map<Integer, Map<String, String>> arr = 
    org.apache.commons.collections.map.LazyMap.decorate(
         new HashMap(), new InstantiateFactory(HashMap.class));

//$arr[0]['name'] = 'demo';
arr.get(0).put("name", "demo");

System.out.println(arr.get(0).get("name"));
System.out.println(arr.get(1).get("name"));    //yields null

1
อะไรLazyMap.decorateและInstantiateFactoryและสิ่งที่หา?
Svish

+1 คำตอบอื่น ๆ ทั้งหมดดูเหมือนว่าสมมติว่าหนึ่งใน "กุญแจ" เป็นจำนวนเต็ม จะเกิดอะไรขึ้นถ้าอาร์เรย์ที่สัมพันธ์กันนั้นยึดตามคีย์ที่ไม่ใช่จำนวนเต็มสองตัว (tuple เราจะพูดเป็นไพ ธ อน) ฉันเชื่อว่าคุณจะต้องใช้วิธีการนี้เนื่องจากการจัดทำดัชนีเป็นไปไม่ได้
demongolem

10

ดูที่อินเตอร์เฟสMapและที่คลาสHashMapที่เป็นรูปธรรม HashMap

วิธีสร้างแผนที่:

Map<String, String> assoc = new HashMap<String, String>();

ในการเพิ่มคู่คีย์ - ค่า:

assoc.put("name", "demo");

เพื่อดึงค่าที่เกี่ยวข้องกับคีย์:

assoc.get("name")

และแน่นอนคุณสามารถสร้างอาร์เรย์ของแผนที่ได้ตามที่คุณต้องการ:

Map<String, String>[] assoc = ...

6

ฉันยังอยู่ในการค้นหาอาร์เรย์ที่เกี่ยวข้องและพบว่ารายชื่อของแผนที่เป็นทางออกที่ดีที่สุด

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class testHashes {

public static void main(String args[]){
    Map<String,String> myMap1 = new HashMap<String, String>();

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

    myMap1.put("URL", "Val0");
    myMap1.put("CRC", "Vla1");
    myMap1.put("SIZE", "Vla2");
    myMap1.put("PROGRESS", "Vla2");

    myMap.add(0,myMap1);
    myMap.add(1,myMap1);

    for (Map<String, String> map : myMap) {
        System.out.println(map.get("URL"));
    }

    //System.out.println(myMap);

}


}


5

Java ไม่มีอาร์เรย์เชื่อมโยงสิ่งที่ใกล้เคียงที่สุดที่คุณจะได้รับคือ แผนที่อินเตอร์เฟส

นี่คือตัวอย่างจากหน้านั้น

import java.util.*;

public class Freq {
    public static void main(String[] args) {
        Map<String, Integer> m = new HashMap<String, Integer>();

        // Initialize frequency table from command line
        for (String a : args) {
            Integer freq = m.get(a);
            m.put(a, (freq == null) ? 1 : freq + 1);
        }

        System.out.println(m.size() + " distinct words:");
        System.out.println(m);
    }
}

หากทำงานด้วย:

java Freq if it is to be it is up to me to delegate

คุณจะได้รับ:

8 distinct words:
{to=3, delegate=1, be=1, it=2, up=1, if=1, me=1, is=2}

3

อาร์เรย์ที่เกี่ยวข้องใน Java เช่นใน PHP:

SlotMap hmap = new SlotHashMap();
String key = "k01";
String value = "123456";
// Add key value
hmap.put( key, value );

// check if key exists key value
if ( hmap.containsKey(key)) {
    //.....        
}

// loop over hmap
Set mapkeys =  hmap.keySet();
for ( Iterator iterator = mapkeys.iterator(); iterator.hasNext();) {
  String key = (String) iterator.next();
  String value = hmap.get(key);
}

ข้อมูลเพิ่มเติมดู Class SoftHashMap: https://shiro.apache.org/static/1.2.2/apidocs/org/apache/shiro/util/SoftHashMap.html


เมธอด Map.containKey () วนซ้ำทุกคีย์ของแผนที่และเมธอด Map.get () ซึ่งจะคืนค่าตามธรรมชาติเมื่อพบคีย์ ดังนั้นเพียงแค่ Map.get () ดำเนินการทั้งเทคนิคเหล่านั้นเพียงครั้งเดียว (เพื่อให้มีประสิทธิภาพมากขึ้น) โดยไม่ต้องเขียนโค้ดใหม่นี้ ด้วย Map.get () จะคืนค่าที่เกี่ยวข้องกับคีย์แรกที่จับคู่แล้วหยุดค้นหาซึ่งเร็วขึ้นและมีพฤติกรรมที่คุ้นเคยสำหรับรูปแบบนี้ รหัสในโพสต์นี้จะวนซ้ำทุกคีย์แม้หลังจากค้นหาคีย์แล้วจะส่งคืนคีย์ที่ตรงกันล่าสุด (ไม่ใช่คีย์ที่จับคู่แรก)
แมทธิว

3

ใช้ ArrayList <Map <String, String>>

นี่คือตัวอย่างรหัส:

ArrayList<Map<String, String>> products = new ArrayList<Map<String, String>>();
while (iterator.hasNext()) {
         Map<String, String> product = new HashMap<String, String>();
         Element currentProduct = iterator.next();
         product.put("id",currentProduct.get("id"));
         product.put("name" , currentProduct.get("name") );
         products.add(product );
}
System.out.println("products : " + products);

ผลผลิต:

ผลิตภัณฑ์: [{id = 0001, name = prod1}, {id = 0002, name = prod2}]


1

ใน JDK 1.5 (http://tinyurl.com/3m2lxju) มีหมายเหตุ: "หมายเหตุ: คลาสนี้ล้าสมัยการใช้งานใหม่ควรใช้อินเตอร์เฟส Map แทนที่จะขยายคลาสนี้" ขอแสดงความนับถือ, N.


1
Object[][] data = {
{"mykey1", "myval1"},
{"mykey2", "myval2"},
{new Date(), new Integer(1)},
};

ใช่สิ่งนี้ต้องการการวนซ้ำเพื่อค้นหาค่าโดยใช้คีย์ แต่ถ้าคุณต้องการทั้งหมดมันจะเป็นตัวเลือกที่ดีที่สุด


0

จริงๆแล้ว Java รองรับอาเรย์ที่เชื่อมโยงกันซึ่งเรียกว่าพจนานุกรม!


10
หากคุณอ้างถึงdownload.oracle.com/javase/1.4.2/docs/api/java/util/ …โปรดทราบว่าคลาสนี้คือ (a) abstract และ (b) เลิกใช้แล้ว
เฟลิกซ์คลิง

0

เมื่อพิจารณาเพิ่มเติมเกี่ยวกับเรื่องนี้ฉันต้องการที่จะทำให้สิ่งอันดับเป็นจุดประสงค์ทั่วไปในการจัดการกับปัญหานี้ แม้ว่าทูเปิลไม่ได้เป็นภาษาจาวา แต่ฉันใช้Javatuplesเพื่อมอบฟังก์ชั่นแบบเดียวกันซึ่งมีอยู่ในภาษาอื่น ตัวอย่างของวิธีจัดการกับคำถามที่ถามคือ

Map<Pair<Integer, String>, String> arr = new HashMap<Pair<Integer, String>, String>();
Pair p1 = new Pair(0, "name");
arr.put(p1, "demo");

ฉันชอบวิธีนี้เพราะสามารถขยายไปยังกลุ่มอเนกประสงค์และกลุ่มอื่น ๆ ที่สั่งซื้อสูงกว่าด้วย api ที่ให้คลาสและวิธีการ


-2

เกี่ยวกับความคิดเห็น PHP 'ไม่ PHP ไม่ชอบ' ที่จริงแล้ว PHP จะทำการตรวจสอบต่อไปจนกว่าคุณจะตั้งระดับข้อยกเว้น / ข้อผิดพลาดบางอย่างที่เข้มงวดมาก (สำหรับ PHP)

สิ่งที่จะเกิดขึ้นตามค่าเริ่มต้นคือการเข้าถึงตัวแปรที่ไม่มีอยู่ / ออกนอกขอบเขตขององค์ประกอบอาร์เรย์ 'ไม่ได้ตั้งค่า' ค่าของคุณที่คุณกำหนดไว้ ไม่นั่นไม่ใช่โมฆะ PHP มีเชื้อสาย Perl / C จากสิ่งที่ฉันเข้าใจ ดังนั้นจึงมี: ตัวแปร unset และ non ที่มีอยู่แล้วค่าที่ตั้ง แต่เป็นค่า NULL ค่าบูลีนเท็จจากนั้นทุกอย่างอื่นที่ langauges มาตรฐานมี คุณต้องทดสอบแยกต่างหากหรือเลือกการประเมิน RIGHT ที่สร้างขึ้นในฟังก์ชั่น / ไวยากรณ์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.